Saving data structures

Could someone suggest a way to save this kind of data structure to disk:


class DerivationLine {
  var formulaString: String?
  var subderivation: [DerivationLine]?
  var justification: String?
  var level: Int = 0


It's the recursive part at line 03 that's got me puzzled.


dkj

What infrastructure are you using for the archiving? NSKeyedArchiver?

I've used NSKeyedArchiver a lot with Objective C. I'd be willing to use it in Swift, if that's possible. So far in Swift I've just been using NSUserDefaults for some small amounts of data. But an array of those DerivationLine objects could get pretty big.


dkj

You can use a keyed archiver, but (I believe) only with descendants of NSObject, which may be a limitation. If you want to invent your own format, it's going to be a lot more work.


The DerivationLine objects look like they're strictly hierarchical. In that case, you could *serialize* your data by walking the tree structure. Each DerivationLine would then be represented by its other properties, plus the number of child DerivationLine objects. Unserialization should then be straightforward, re-building the hierarchy by walking the serialized data.


I wouldn't necessarily worry about the size of the archive until you know what you're worrying about. If there are so many nested objects that it really matters, your archive is going to be pretty large regardless of what you do.

NSArray's writeToFile method looks very enticing. I could make the DerivationLine class inherit from NSObject. But again, it's the recursive part that I'm wondering how to handle.

It's not a good choice. The actual file data is going to be in an unknown file format, unless you archive a property list, in which case you're going to have to create an in-memory near-duplicate of your custom-class-based data structure. You also have to worry about architecture dependencies (number of bytes per int, byte order, etc). And this is likely to be a fairly inefficient format, in ways that you can't directly improve.


Generally, my advice is to generally regard API that takes file paths as obsolescent, since all modern APIs have a URL form. In this case, there is a writeToURL method too, but you can tell that it is also obsolescent because it has no outError parameter (or, in Swift, does not throw an error).


API like NSArray's writeToFile/writeToURL is appropriate for pushing data to files temporarily during the execution of your app, and it's not very suitable for longer term saves. Avoid them otherwise.


Again, I think the recursive class reference is the least of your difficulties. Designing an approach that is robust and future-proof is much harder.


How about serializing your object properties into JSON, using nested JSON dictionaries for the recursion, then writing the JSON to disk as UTF-8 text? The class you've shown should be simple enough to convert manually, or poke around github (etc) for open source code that assists in this sort of task.

A couple of years ago I wrote an Objective C app that saved data as XML files. I remember there was some nice API for doing that.


PS: I've been googling JSON and it looks a lot simpler than XML. I'll definitely have a look at doing it the way you suggest.

All I really need to save is an array of these things:


class DerivationLine {
  var formula: String?
  var subderivation: [String]?
}


One and only one of the two variables will have a value. I can reconstruct everything else once this array is loaded. But after trying various formulations, I can't find a way of using NSJSONSerialization to do it: I keep getting invalid JSON object errors when I try using the dataWithJSONObject method. And I can't seem to find a straightforward example of how to do this on the web. It should be simple, and I'm sure it is. What am I missing?

dataWithJSONObject requires you to give it a hierarchical structure of JSON objects, which is a subset of NSObject types similar to (but more limited than) the types allowed by a property list serialization. (So: numbers, arrays, dictionaries, strings, basically.)


So you have the choice of creating a parallel data structure in memory that represents you entire data model, or you're going to have to do something a bit more manual to generate bits of JSON as you serialize.


Using JSON isn't really much different from using property list serializations, except that (a) it's a bit simpler, (b) it always produces a text representation, and (c) there's a cross-platform standard.

Saving data structures
 
 
Q