JSON Can't be Deserialized to Object, Needs Array?

ⅰ亾dé卋堺 提交于 2019-11-30 23:58:48

Ok, you mention that genetics and price are arrays, but the returned JSON only contains one item. The rest of your RootObject are simple string properties.

Since you did not post a raw JSON example. Let me present a trimmed down version, to keep things simple and short.

{
    "url": "http://www.stackoverflow.com",
    "display": "This is a test",
    "genetics": [
        "typeophere"
    ],
    "price": [
        "$1400"
    ],
    "form": "a form"
}

Now we can trim down the RootObject class type. I used Pascal casing for my properties and attributed them with JSON.NET attributes to assist with the deserialing / serializing.

[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
public class RootObject
{
    [JsonProperty(PropertyName = "url")]
    public string Url { get; set; }

    [JsonProperty(PropertyName = "display")]
    public string Display { get; set; }

    [JsonProperty(PropertyName = "genetics")]
    public List<string> Genetics { get; set; }

    [JsonProperty(PropertyName = "price")]
    public List<string> Price { get; set; }

    [JsonProperty(PropertyName = "form")]
    public string Form { get; set; }
}

Since I don't know the web service you are calling I just stored this JSON in a text file. Marked it as an embedded resource and read it from there.

string json;
var resource = Application.GetResourceStream(new Uri("json.txt", UriKind.Relative));
using (var reader = new StreamReader(resource.Stream))
{
    json = reader.ReadToEnd();
}

Just replace this part with your WebClient call to obtain your JSON data.

Now we can deserialize the JSON into a RootObject instance.

var rootObject = JsonConvert.DeserializeObject<RootObject>(json);

Works as advertised. Now you need to bind it to a ListBox control. If you hover over the ItemSource property of your ListBox instance you'll see that the tooltip mentions that you can bind it to a collection. Well a single rootObject isn't a collection. You can't bind it directly.

lstBoxResults.ItemsSource = rootObject;

This will NOT work. You cannot convert a RootObject instance to a System.Collections.IEnumerable. Which is what ItemsSource is expecting.

Easy fix. Let's create a collection.

lstBoxResults.ItemsSource = new List<RootObject> { rootObject };

This is assuming that your JSON data only returns one rootObject. Only one item will appear in your ListBox.

Now let's suppose your JSON data returns an array of RootObjects. For example an array called "items" which contains a collection of RootItems.

{
    "items": [
    {
    "url": "http://www.stackoverflow.com",
    "display": "This is a test",
    "genetics": [ "typeophere" ],
    "price": [ "$1400" ],
    "form": "a form"        
    },
    {
    "url": "http://cgeers.com",
    "display": "This is another test",
    "genetics": [ "typeophere" ],
    "price": [ "$2000" ],
    "form": "another form"
    }]
}

Deserialing this is equally easy. Using JSON.NET obtain the collection of RootObjects.

var data = JObject.Parse(json)["items"];

Now deserialize into a collection (IEnumerable).

var rootObjects = JsonConvert.DeserializeObject<IEnumerable<RootObject>>(data.ToString());

Since you now already have a collection of RootObject there is no need to create one yourself. You can directly bind it to the ListBox.

lstBoxResults.ItemsSource = rootObjects;

Seems like the JSON data you receive is invalid. Just before parsing it make sure you modify it so that you have a valid JSON object.

For example:

json = json.Substring(json.IndexOf("[") + 1);
json = json.Substring(0, json.LastIndexOf("]"));
var rootObjects = JsonConvert.DeserializeObject<RootObject>(json);

Try this

RootObject rootObject;

if (json.startsWith("["))
{
  rootObject = JsonConvert.DeserializeObject<List<RootObject>>(json)[0];
}
else
{
  rootObject = JsonConvert.DeserializeObject<RootObject>(json);
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!