Objects that point to each other

Mar 14, 2012 at 3:14 PM

I apologize; this has probably already been answered but I can't seem to find the right search terms.

I have several C# objects that point to each other, and I'm having trouble getting Json.NET to serialize them and maintain their connections.  Here is basically how I have my program structured:

Class Project
{
    Place[] PlaceList
}

Class Place
{
Group[] GroupList
Thing1[] Thing1List // each Thing1 is referenced by one or more Group objects Thing2[] Thing2List // each Thing2 is referenced by one or more Group objects } Class Group {
Project owner // the project that contains this group
 Thing1[] Thing1List // subset of Place.Thing1List Thing2[] Thing2List // subset of Place.Thing2List } Class Thing1 { Project owner // the project that contains this thing } Class Thing2 { Project owner // the project that contains this thing }

There is of course other data for each of the objects, but I am just trying to show how they are linked to each other.

My goal is to serialize a Project object and save it to a file, and then reload it later.  My first attempt was to just use JsonConvert.SerializeObject(projectInstance, Formatting.Indented), but that gave me some kind of "objects are referencing each other" error.  I added new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore }, but that created an infinite loop.

Now I knew I had to somehow tell Json.NET how to handle my objects.  Here was my first attempt:

Class Place
{
    Thing1[] Thing1List
    Thing2[] Thing2List
    Group[] GroupList // this is now after the Things

    // the argument is a hackish way of making sure that I don't confuse this constructor with other constructors
    [JsonConstructor] public Place(JsonConstructorAttribute nothing)
    {
        global.CurrentPlace = this;
    }
}

Class Group
{
    private owner // json ignores this for now

    private Thing1[] Thing1List public int[] Thing1List // Json now stores these as ints
{
get
{
for (0 <= i < Thing1.Length)
result[i] = owner.Thing1List.IndexOf(Thing1List[i])
}
set
{
for (0 <= i < value.Length)
Thing1List[i] = owner.Thing1List[value[i]]
}
} [JsonConstructor] public Group(JsonConstructorAttribute nothing) { owner = global.CurrentPlace; } }

Now the Project object gets serialized without error, and the resulting json file looked just how I expected.  Now the problem was loading it up, where I got a few errors from trying to index null objects.  With some help from the debugger, I discovered that this was when deserializing these objects, some of them were calling their constructors BEFORE loading members (as I would expect), but other objects were being constructed AFTER loading their members, which is quite baffling.

If I can force the constructor to be called before the members are deserialized, then I think this should work just how I want it to.  Unless there is an easier way :)

Mar 16, 2012 at 8:39 PM

I got around this by using C#'s built-in DataContractSerializer.  This method actually doesn't call any initializer, but allows you to set up a method that is run when deserializing.  More information here: http://msdn.microsoft.com/en-us/library/ms731073.aspx