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

前端 未结 2 874
闹比i
闹比i 2021-01-06 11:35

I am trying to take the incoming JSON items and bind them to listbox items but I am told by visual studio that I need to do an Array and not Object? I\'ve never had to do th

相关标签:
2条回答
  • 2021-01-06 12:04

    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);
    
    0 讨论(0)
  • 2021-01-06 12:17

    Try this

    RootObject rootObject;
    
    if (json.startsWith("["))
    {
      rootObject = JsonConvert.DeserializeObject<List<RootObject>>(json)[0];
    }
    else
    {
      rootObject = JsonConvert.DeserializeObject<RootObject>(json);
    }
    
    0 讨论(0)
提交回复
热议问题