Deserialization problem with DataContractJsonSerializer
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.
Related videos on Youtube
bbrown
Development manager at a golf club manufacturer, formerly at GoDaddy
Updated on July 09, 2022Comments
-
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
, andlabel
are required butitems
andrules
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
andrules
are empty for the firstFooDef
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 tryHashtable
, which seemed like an obvious candidate. Didn't work.]The problem, as I see it, is that the key piece under
items
andrules
is open-ended. That is, it's not always going to be calledrange
or3
. Any advice or ideas? -
bbrown about 15 yearsThat'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 about 15 yearsI tried it with JavaScriptSerializer and it worked perfectly. I ended up using Dictionary<string, string> but Hashtable worked also.