dasheddot
dasheddot

Reputation: 2966

Deserialize Dictionary with JSON.NET

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?

Upvotes: 2

Views: 7320

Answers (4)

Dictionary<string, object> result = JsonConvert.DeserializeObject<Dictionary<string, object>>(strJsonResult);

Upvotes: 1

JamieSee
JamieSee

Reputation: 13010

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}

Upvotes: 0

Rawling
Rawling

Reputation: 50114

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

Upvotes: 1

L.B
L.B

Reputation: 116118

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

Upvotes: 3

Related Questions