Luke Cardeaux
Luke Cardeaux

Reputation: 791

Dictionary Serialization -- Problems when reading object serialized by DataContractSerializer

I've hit a snag when working on serialization of Dictionary collections using the standard .NET DataContractSerializer class. It seems to serialize the dictionary correctly:

<GameObjectData xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
    <Id>
      <GameObjectData>ddd95b29-0e98-4f1c-8c0a-ef2815a90f78</GameObjectData>
      <d2p1:Value xmlns:d4p1="https://id.unity.com/en/organizations/lucas-cardoso-2534099">
        <X>-4.10677576</X>
        <Y>0.05</Y>
        <Z>1.01642287</Z>
      </d2p1:Value>
    </Id>
    <Id>
      <GameObjectData>7a7b90d6-975d-4166-93a0-f45b4fd0bf51</GameObjectData>
      <d2p1:Value xmlns:d4p1="https://id.unity.com/en/organizations/lucas-cardoso-2534099">
        <X>0.84188956</X>
        <Y>0.05</Y>
        <Z>0.09239852</Z>
      </d2p1:Value>
    </Id>
  </GameObjectData>

But when trying to read the object from file, it complains as if it didn't expect it to be an array of key-value pairs:

SerializationException: Deserializing type 'NodeGameObjectDict'. Expecting state 'EndElement'. Encountered state 'Element' with name 'Id' with namespace 'https://id.unity.com/en/organizations/lucas-cardoso-2534099'

The most damning thing is it actually works if the Dictionary has only one Key-Value pair, so it's definitely hitting a snag thinking it's not actually an array. What gives?

This is the code I'm using:

[DataContract(Name = "NodeGraphContainer", Namespace = "https://id.unity.com/en/organizations/lucas-cardoso-2534099")]
public class NodeGraphContainer {

...

    [DataMember(Name = "GameObjectData")]
    public NodeGameObjectDict nodeGameObjectData;

...

}

...


[CollectionDataContract(ItemName = "Id", KeyName = "GameObjectData", Namespace = "https://id.unity.com/en/organizations/lucas-cardoso-2534099")]
public class NodeGameObjectDict : Dictionary<Guid, NodeGameObjectData> { }

And my serialization/deserialization code:

public void Serialize() {
        DataContractSerializer serializer = new DataContractSerializer(typeof(NodeGraphContainer));
        XmlWriterSettings settings = new XmlWriterSettings() { Indent = true };
        XmlWriter writer = XmlWriter.Create(new FileStream("Assets/Data/maptest.xml", FileMode.Create), settings);
        serializer.WriteObject(writer, this);
        writer.Close();
    }

    public static NodeGraphContainer Deserialize() {
        DataContractSerializer serializer = new DataContractSerializer(typeof(NodeGraphContainer));
        try {
            XmlReader reader = XmlDictionaryReader.Create(new FileStream("Assets/Data/maptest.xml", FileMode.Open));
            NodeGraphContainer container = (NodeGraphContainer)serializer.ReadObject(reader);
            reader.Close();
            return container;
        } catch (FileNotFoundException ex) {
            Debug.Log("No map file found");
            return null;
        }
    }

Upvotes: 1

Views: 214

Answers (1)

Luke Cardeaux
Luke Cardeaux

Reputation: 791

The actual answer is that Unity does not implement .NET correctly, so Dictionary classes aren't being deserialized correctly. A short test case proved that suspicion. Already reported the bug!

Upvotes: 0

Related Questions