.netc#-4.0datacontractjsonserializer

How to serialize object array with a dictionary inside


I'm trying to serialize an object array which contains a dictionary as one of its values, and I'm getting this run-time SerializationException:

Type 'System.Collections.Generic.Dictionary`2 ...with data contract name 'ArrayOfKeyValueOfstringanyType
is not expected. Consider using a DataContractResolver if you are using 
DataContractSerializer 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 the serializer.

This is how I'm trying to accomplish the task:

        object[] taskArgs = new object[] { 1, 2 };
        IDictionary<string, object> kwargs = new Dictionary<string, object>();
        IDictionary<string, object> embed = new Dictionary<string, object>();
        embed.Add("callbacks", null);
        embed.Add("errbacks", null);
        embed.Add("chain", null);
        embed.Add("chord", null);


        var knownTypes = new List<Type> { typeof(IDictionary<string, object>), typeof(object []), typeof(List<string>) };
        //object[] arguments = new object[] { taskArgs, "{}", "{}"  };
        object[] arguments = new object[] { taskArgs, kwargs, embed };

        MemoryStream stream1 = new MemoryStream();
        DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(object[]), knownTypes);
        ser.WriteObject(stream1, arguments);
        stream1.Position = 0;
        StreamReader sr = new StreamReader(stream1);
        string message = sr.ReadToEnd();

Even though I've tried to add typeof(IDictionary<string, object>) to knownTypes, it won't work.


Solution

  • You must use the concrete type typeof(Dictionary<string, object>) instead of the interface type typeof(IDictionary<string, object>) for a known type:

    var knownTypes = new List<Type> { typeof(Dictionary<string, object>), typeof(object[]), typeof(List<string>) };
    

    A type in the list of known types much match the exact type (as returned by GetType()) of an object of otherwise unknown type to take effect. Matching a base class type or implemented interface type is not sufficient, and in any event the data contract serializers do not support serializing interfaces.