I want to avoid reinventing the wheel when serializing data. I know some ways to serialize objects which are linked to each other, but it ranges from writing some code to writing a lot of code for serialization, and I’d like to avoid that. There must be some generic solutions.
Let’s say I have a structure like this:
Person
bro = new Person { name = "bro", pos = new Pos { x = 1, y = 5 } },
sis = new Person { name = "sis", pos = new Pos { x = 2, y = 6 } },
mom = new Person { name = "mom", pos = new Pos { x = 3, y = 7 },
children = new List<Person> { bro, sis }
},
dad = new Person { name = "dad", pos = new Pos { x = 4, y = 8 },
children = new List<Person> { bro, sis }, mate = mom
};
mom.mate = dad;
Family family = new Family { persons = new List<Person> { mom, dad, bro, sis } };
I want to serialize data to something like this:
family: {
persons: [
{ name: "bro", pos: { x: 1, y: 5 } },
{ name: "sis", pos: { x: 2, y: 6 } },
{ name: "mom", pos: { x: 3, y: 7 }, mate: "dad", children: [ "bro", "sis" ] },
{ name: "dad", pos: { x: 4, y: 8 }, mate: "mom", children: [ "bro", "sis" ] },
]
}
Here, links are serialized as just names, with the assumption that names are unique. Links can also be “family.persons.0” or generated unique IDs or whatever.
Requirements:
-
Format must be human-readable and preferably human-writable too. So, in order of preference: JSON, YAML*, XML, custom. No binary formats.
-
Serialization must support all good stuff .NET offers. Generics are a must, including types like IEnumerable<>, IDictionary<> etc. Dynamic types / untyped objects are desirable.
-
Format must not be executable. No Lua, Python etc. scripts and things like that.
-
If unique IDs are generated, they must be stable (persist through serialization-deserialization), as files will be put into a version control system.
* Heard about YAML, but sadly, it seems to be pretty much dead.
Solved the problem using JSON.NET (fantastic library!). Now objects are, first, serialized and referenced exactly where I want them them to; and second, without numerous “$id” and “$ref” fields. In my solution, the first property of an object is used as its identifier.
I’ve created two
JsonConvertors (for references to objects and for referenced objects):and a context to hold references data (with a dictionary for each type, so IDs need to be unique only among objects of the same type):
Some attributes on the properties are necessary:
So, when I serialize and deserialize using this code:
I get this neat JSON:
What I don’t like in my solution, is that I have to use
JObject, even though technically it’s unnecessary. It probably creates quite a bit of objects, so loading will be slower. But looks like this is the most widely used approach for customizing convertors of objects. Methods which could be used to avoid this are private anyway.