Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DataContractSerializer and Dictionary<string,object> fails when reading

I'm using DataContractSerializer to serialize an object that contains a Dictionary<string,object> member, which is marked with [DataMember()]. The idea is to have a flexible bag of object attributes, and I don't know what those attributes could be.

This works great when I'm putting int, double and string objects into the dictionary, but when I put a List<string> in it fails to deserialize the object with:

System.InvalidOperationException: Node type Element is not supported in this operation.

The entire dictionary is serialized to XML, and it looks pretty reasonable:

<Attributes xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
    <d2p1:KeyValueOfstringanyType>
        <d2p1:Key>name</d2p1:Key>
        <d2p1:Value xmlns:d4p1="http://www.w3.org/2001/XMLSchema" i:type="d4p1:string">Test object</d2p1:Value>
    </d2p1:KeyValueOfstringanyType>
    <d2p1:KeyValueOfstringanyType>
        <d2p1:Key>x</d2p1:Key>
        <d2p1:Value xmlns:d4p1="http://www.w3.org/2001/XMLSchema" i:type="d4p1:double">0.5</d2p1:Value>
    </d2p1:KeyValueOfstringanyType>
    <d2p1:KeyValueOfstringanyType>
        <d2p1:Key>y</d2p1:Key>
        <d2p1:Value xmlns:d4p1="http://www.w3.org/2001/XMLSchema" i:type="d4p1:double">1.25</d2p1:Value>
    </d2p1:KeyValueOfstringanyType>
    <d2p1:KeyValueOfstringanyType>
        <d2p1:Key>age</d2p1:Key>
        <d2p1:Value xmlns:d4p1="http://www.w3.org/2001/XMLSchema" i:type="d4p1:int">4</d2p1:Value>
    </d2p1:KeyValueOfstringanyType>
    <d2p1:KeyValueOfstringanyType>
        <d2p1:Key>list-of-strings</d2p1:Key>
        <d2p1:Value>
            <d2p1:string>one string</d2p1:string>
            <d2p1:string>two string</d2p1:string>
            <d2p1:string>last string</d2p1:string>
        </d2p1:Value>
    </d2p1:KeyValueOfstringanyType>
</Attributes>

Note the list-of-strings at the end there. It's got all the values but nothing indicating that it's a List<string> or anything.

What's the correct way of handling this situation?

like image 431
Chris Herborth Avatar asked Oct 01 '11 14:10

Chris Herborth


Video Answer


1 Answers

Try using the KnownTypeAttribute so that DataContractSerializer knows about the List<string> type. Unfortunately, that seems to go against your idea of not having to know about the types before hand.

I'm basing this on the following code, which uses DataContractSerializer to serialize a Dictionary<string, object> containing List<string>:

Dictionary<string,object> dictionary = new Dictionary<string, object>();

dictionary.Add("k1", new List<string> { "L1", "L2", "L3" });

List<Type> knownTypes = new List<Type> { typeof(List<string>) };
DataContractSerializer serializer = new DataContractSerializer(typeof(Dictionary<string,object>), knownTypes);
MemoryStream stream = new MemoryStream();

serializer.WriteObject(stream, dictionary);

StreamReader reader = new StreamReader(stream);

stream.Position = 0;
string xml = reader.ReadToEnd();

If you knownTypes is not provided to the DataContractSerializer, it throws an exception.

SerializationException: Type 'System.Collections.Generic.List`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]' with data contract name 'ArrayOfstring:http://schemas.microsoft.com/2003/10/Serialization/Arrays' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.

like image 194
Jeff Ogata Avatar answered Sep 21 '22 15:09

Jeff Ogata