Deserialization problem with DataContractJsonSerializer

55,836

Solution 1

IMHO there is no way to deserialize the JSON string you provided into a .NET class using DataContractJsonSerializer.

The problem comes from the way DataContractJsonSerializer serializes dictionaries. You could use an alternative serializer such as Json.NET (which I strongly recommend) or JavaScriptSerializer (I think it was deprecated in favor of DataContractJsonSerializer but it will work for your scenario).

You can also read these rants.

Documentation: Serializing Collections - Json.NET

Solution 2

http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/071f73bb-e141-4a68-ae61-05635382934f

Check this article out - it solved my problem almost perfectly. I had to change their object[] Type to a string, but i'm only using strings:string type Key/Value pairs, so no problems there.

Share:
55,836

Related videos on Youtube

bbrown
Author by

bbrown

Development manager at a golf club manufacturer, formerly at GoDaddy

Updated on July 09, 2022

Comments

  • bbrown
    bbrown almost 2 years

    I've got the following piece of JSON:

    [{
        "name": "numToRetrieve",
        "value": "3",
        "label": "Number of items to retrieve:",
        "items": {
            "1": "1",
            "3": "3",
            "5": "5"
        },
        "rules": {
            "range": "1-2"
        }
    },
    {
        "name": "showFoo",
        "value": "on",
        "label": "Show foo?"
    },
    {
        "name": "title",
        "value": "Foo",
        "label": "Foo:"
    }]
    

    All in one line version (suitable for a string literal):

    [{\"name\":\"numToRetrieve\",\"value\":\"3\",\"label\":\"Number of items to retrieve:\",\"items\":{\"1\":\"1\",\"3\":\"3\",\"5\":\"5\"},\"rules\":{\"range\":\"1-2\"}},{\"name\":\"showFoo\",\"value\":\"on\",\"label\":\"Show foo?\"},{\"name\":\"title\",\"value\":\"Foo\",\"label\":\"Foo:\"}]
    

    In the above example, name, value, and label are required but items and rules are optional.

    Here's the class I'm trying to deserialize into:

    using System.Collections;
    using System.Collections.Generic;
    using System.Runtime.Serialization;
    
    namespace foofoo
    {
        [DataContract]
        public sealed class FooDef
        {
            [DataMember(Name = "name", IsRequired = true)]
            public string Name { get; set; }
    
            [DataMember(Name = "value", IsRequired = true)]
            public string Value { get; set; }
    
            [DataMember(Name = "label", IsRequired = true)]
            public string Label { get; set; }
    
            [DataMember(Name = "items", IsRequired = false)]
            public Dictionary<string, string> Items { get; set; }
    
            [DataMember(Name = "rules", IsRequired = false)]
            public Dictionary<string, string> Rules { get; set; }
        }
    }
    

    Here's the code I use to deserialize:

    var json = new DataContractJsonSerializer(typeof(List<FooDef>));
    var bar = "[{\"name\":\"numToRetrieve\",\"value\":\"3\",\"label\":\"Number of items to retrieve:\",\"items\":{\"1\":\"1\",\"3\":\"3\",\"5\":\"5\"},\"rules\":{\"range\":\"1-2\"}},{\"name\":\"showFoo\",\"value\":\"on\",\"label\":\"Show foo?\"},{\"name\":\"title\",\"value\":\"Foo\",\"label\":\"Foo:\"}]";
    var stream = new MemoryStream(Encoding.UTF8.GetBytes(bar));
    var foo = json.ReadObject(stream);
    stream.Close();
    

    Everything goes reasonably well except that items and rules are empty for the first FooDef pass. I have tried everything under the sun to try and get them populated: custom classes, NameValueCollection, KeyValuePair<string, string>, List of both of the latter, and every other collection that seemed to apply. [EDIT: I forgot to try Hashtable, which seemed like an obvious candidate. Didn't work.]

    The problem, as I see it, is that the key piece under items and rules is open-ended. That is, it's not always going to be called range or 3. Any advice or ideas?

  • bbrown
    bbrown about 15 years
    That's kind of what I feared. I was avoiding switching over to JavaScriptSerializer because of the deprecation, but I'm glad to hear that it was undeprecated in 3.5 SP1. I'll try it using that class.
  • bbrown
    bbrown about 15 years
    I tried it with JavaScriptSerializer and it worked perfectly. I ended up using Dictionary<string, string> but Hashtable worked also.