devfunkd devfunkd - 3 months ago 12
JSON Question

Unable to parse JSON with empty array/objects

Trying the parse this json file and it seems to be getting stuck on empty objects and arrays.


{"Unexpected character encountered while parsing value: [. Path 'notes'."}


{
"id":null,
"phone":null,
"name":" ",
"email":null,
"address":null,
"assignee":null,
"notes":[

],
"created_at":null,
"items":{
"0":{
"minimized":false,
"sku":{
"partner_id":null,
"type_id":0,
"errors":{

}
}
}
}
}


CLASSES

public class RootObject
{
public string id { get; set; }
public string phone { get; set; }
public string name { get; set; }
public string email { get; set; }
public string address { get; set; }
public string assignee { get; set; }
public string notes { get; set; }
public string created_at { get; set; }
public Items items { get; set; }
}

public class Items
{
public bool minimized { get; set; }
public Sku sku { get; set; }
}

public class Sku
{
public int partner_id { get; set; }
public int type_id { get; set; }
public Errors errors { get; set; }
}


public class Errors
{
}


The issue appears to be with handling the Notes and Errors property, I've tried to use the following settings as per a few other SO posts but nothing has worked and I am not sure how to get this to deserialize into an object.

RootObject o = JsonConvert.DeserializeObject<RootObject>(json, new JsonSerializerSettings
{
MissingMemberHandling = MissingMemberHandling.Ignore,
NullValueHandling = NullValueHandling.Ignore
});


Perhaps someone can help me out because it seems to me JSON.net should be able to handle these properties?

Answer

Here's a working dotNetFiddle: https://dotnetfiddle.net/Lnkojw

Here's the output.

enter image description here

NOTE: I put in sample values in your json for your null values so you can see that it is working)

Your class definitions (autogenerated from http://json2csharp.com/ ) need to be modified as shown below.

public class RootObject
{
    public string id { get; set; }
    public string phone { get; set; }
    public string name { get; set; }
    public string email { get; set; }
    public string address { get; set; }
    public string assignee { get; set; }
    public List<string> notes { get; set; }
    public string created_at { get; set; }
    public Dictionary<int,Item> items { get; set; }
}

public class Item
{
    public bool minimized { get; set; }
    public Sku sku { get; set; }
}

public class Sku
{
    public int partner_id { get; set; }
    public int type_id { get; set; }
    [JsonIgnore]
    public object errors { get; set; }
}

Since you have stated in comments that Errors will always be empty, I removed that redundant Errors class you had, with no properties or members. I also set the errors member in the Sku class to be object type in case you get values in future. Finally I set this errors property to [JsonIgnore] so json.net will ignore it for serialization / deserialization

Also Items appears to be Dictionary with an int for key and an Item for Value. So I have changed the definition there also.

Here's the code that deserializes and prints out the values.

using System;
using Newtonsoft.Json;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        string json = @"{
                           ""id"":1,
                           ""phone"":""415-000-1234"",
                           ""name"":"" "",
                           ""email"":null,
                           ""address"":null,
                           ""assignee"":null,
                           ""notes"":[

                           ],
                           ""created_at"":null,
                           ""items"":{
                              ""0"":{
                                 ""minimized"":false,
                                 ""sku"":{
                                    ""partner_id"":21,
                                    ""type_id"":44,
                                    ""errors"":{

                                    }
                                 }
                                }
                            }
                        }";


        Console.WriteLine("Deserializing json...");
        RootObject o = JsonConvert.DeserializeObject<RootObject>(json, new JsonSerializerSettings
        {
            MissingMemberHandling = MissingMemberHandling.Ignore,
            NullValueHandling = NullValueHandling.Ignore
        });     
        Console.WriteLine("Success!");
        Console.WriteLine("id #: {0}",o.id);
        Console.WriteLine("phone #: {0}",o.phone);
        foreach (var item in o.items)
        {           
            Console.WriteLine("  Item #: {0}",item.Key);
            if (item.Value != null)
            {
                Console.WriteLine("    SKU: partner_id: {0}",item.Value.sku.partner_id);    
                Console.WriteLine("    SKU: type_id: {0}",item.Value.sku.type_id);  
            }
        }       
    }
}

And once again, here's the output. You can see the json values properly deserialized.

enter image description here

PRO TIPS:

  1. Use a sample json that has values for as many fields as possible, so that http://json2csharp.com/ can generate the proper classes
  2. Whenever you have a nameless property like the items in your json,you will likely need to inspect what http://json2csharp.com/ generated and modify it to be a Dictionary or a NameValuePair or KeyValuePair` or something else. It is on a case by case basis. In other words, for 99% of well designed json, you can "plug and play" with http://json2csharp.com/ , for the remaining 1% you will have to customize the classes generated, or your serialization code or both.
Comments