2

I am using Newtonsoft.Json with version 4.0.8 and trying to use it with Web API. So I wanted to deserialize JSON with

JsonConvert.DeserializeObject<AClass>(jsonString);

This works until I added a Dictionary as property to this class and wanted to deserialize it.

The json string is in the form of

{ 
   "Date":null,
   "AString":"message",
   "Attributes":[
                   {"Key":"key1","Value":"value1"},      
                   {"Key":"key2","Value":"value2"}
                ],
    "Id":0,
    "Description":"...
}

When deserializing exception of type JsonSerializationException occures with message: "Cannot deserialize JSON array into type 'System.Collections.Generic.Dictionary`2[System.String,System.String]'."

What am I doing wrong here?

UPDATE1: When serializing with JSON.NET i get the following for the dictionary:

Attributes":{"key1":"value1","key2":"value2"}

Seems that WebApi deserializes the object in an other way than Json.Net would. Server side I use following line for implicit deserializing:

return new HttpResponseMessage<AClass>(object);

UPDATE2: As a workaround I came now to following line server side.

return new HttpResponseMessage<string>(JsonConvert.SerializeObject(license).Base64Encode());

I convert it with Json.Net server side and transfer it as base64 encoded string. So Json.Net can deserialize its own format.

But its still not that what I want, so are thery any further suggestions?

vestland
  • 55,229
  • 37
  • 187
  • 305
dasheddot
  • 2,936
  • 4
  • 26
  • 33
  • 1
    What JSON do you get if you serialize the class? – Rawling May 14 '12 at 14:41
  • Thanks for your fast response. I updated my question accordingly. – dasheddot May 14 '12 at 14:48
  • 1
    Unless there's an option on either the Web API or Newtonsoft to make it handle dictionaries in the "opposite" manner, I'd just suggest using the same library on each end (serialize/deserialize) if at all possible. – Rawling May 14 '12 at 15:02

4 Answers4

3

It should work if you declare Attributes as List<KeyValuePair<string, string>>

L.B
  • 114,136
  • 19
  • 178
  • 224
1

From this post, calling

JsonConvert.SerializeObject(yourObject, new KeyValuePairConverter());

gets your JSON in the format that the Web API is creating for you.

Ergo, one might assume that calling

JsonConvert.DeserializeObject<AClass>(jsonString, new KeyValuePairConverter());

will do the reverse and correctly handle the Web API's style.

I have no idea whether this overload even exists, though; give it a try and see what happens...

Community
  • 1
  • 1
Rawling
  • 49,248
  • 7
  • 89
  • 127
1
Dictionary<string, object> result = JsonConvert.DeserializeObject<Dictionary<string, object>>(strJsonResult);
0

If it's .NET 4, you can use DataContract attributes and the DataContractJsonSerializer Class to enforce the message format:

    [DataContract]
    public class Message
    {
        [DataMember]
        public DateTime? Date { get; set; }
        [DataMember]
        public string AString { get; set; }
        [DataMember]
        public Dictionary<string, string> Attributes { get; set; }
        [DataMember]
        public int Id { get; set; }
        [DataMember]
        public string Description { get; set; }
    }

        DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(Message));

        Message message = null;
        using (MemoryStream jsonStream = new MemoryStream(Encoding.UTF8.GetBytes(jsonString)))
        {
            // Deserialize
            message = (Message)jsonSerializer.ReadObject(jsonStream);

            // Go to the beginning and discard the current stream contents.
            jsonStream.Seek(0, SeekOrigin.Begin);
            jsonStream.SetLength(0);

            // Serialize
            jsonSerializer.WriteObject(jsonStream, message);
            jsonString = Encoding.UTF8.GetString(jsonStream.ToArray());
        }

Serializing this back out produces the following JSON:

{"AString":"message","Attributes":[{"Key":"key1","Value":"value1"},{"Key":"key2","Value":"value2"}],"Date":null,"Description":"...","Id":0}
JamieSee
  • 12,696
  • 2
  • 31
  • 47
  • 2
    Thanks, but i want to do it with Json.Net since we are using it on several places in the solution already so i not really want to use .Nets DataContractSerializer any more. – dasheddot May 15 '12 at 08:03