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?
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.