user3161621
user3161621

Reputation: 77

How do I serialize circular references?

How do I serialise objects referencing each other?

public class Item {}

public class Player
{
    Item weapon;
}

Those instances live on their own somewhere: I have in some class a List<Item> gameobjects and in another class a tile class with a List<Item> tileobjects.

Upvotes: 0

Views: 1158

Answers (1)

TheWanderer
TheWanderer

Reputation: 244

Here's how I solved a similar problem. Your serializer class should then keep track of those objects you have already serialized. For example, by adding its ID in a list of already parsed objects. If it is the first time, you should continue serializing the object, otherwise you can just write the ID.

When deserializing, recover this ID and check in your serializer class whether that object has already been deserialized. If so, recover the actual object and reconstruct the reference. Otherwise, deserialize the object and add its ID to another list of already deserialized objects.

For example, you might have a class like the following:

public class GraphSerializer 
{
    Dictionary<string, Node> parsedNodes;

    public void MarkNodeAsParsed(Node node)
    {
        parsedNodes.Add(node.Id, node);
    }

    public bool IsNodeParsed(string id)
    {
        return parsedNodes.ContainsKey(id);
    }

    public Node GetNode(string id)
    {
        return parsedNodes[id];
    }

    [...]
}

Now when serializing you would do something like this, in pseudocode:

public void Serialize(GraphSerializer serializer, ...)
{
    serializer.Write(node.Id);

    bool isNewNode = !serializer.IsNodeParsed(node.Id);
    if (isNewNode) 
    {
        // Write rest of data
        serializer.Write(node);
        serializer.MarkNodeAsParsed(node);
    }

    // Since this node has already been serialized, we don't need  
    // to serialize any other value as we have already written the node Id
}

Then, when deserializing:

public void Deserialize(GraphSerializer serializer, ...)
{
    string id = serializer.ReadString();
    Node node;

    bool isNewNode = !serializer.IsNodeParsed(node.Id);
    if (isNewNode) 
    {
        // Read rest of data
        node = serializer.Read();
        serializer.MarkNodeAsParsed(node);
    }
    else
    {
        // Node has already been deserialized, so we can just recover it
        node = serializer.GetNode(id);
    }
}

Upvotes: 1

Related Questions