Click here to Skip to main content
14,921,505 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have to deserialize a JSON string to C# classes inorder to bind to a grid. I have implemented the respective classes in C#. But at a particular instance, this fails because the JSON property will be either an array or an object. Please check a part of the string.

I have created ItemList class with 3 properties IL1 , Name and another object class "Item". However, you can see that when the property "Name" is Rubber, I should have List of Item class as a property rather than Item object. When it is Rubber, it returns array of 2 items. How can I parse this to a C# class effectively and the easiest way to get this done?

XML
"ItemList": [
{
  "@IL1": "Yes",
  "@Name": "Pencil"
  "Item": {
    "@ItemType": "Pencil",
    "@Item2": "1A7716744F7048ACA2549BE93F0A2BF1",        
    "aimLink": {
      "@id": "1A7716744F7048ACA2549BE93F0A2BF1",
      "@DisplayText": "P00001"         
    }
  }
},
{
  "@IL1": "Yes",
  "@Name": "Pen",    
  "Item": {
    "@ItemType": "Pen",
    "@Item2": "AE067F7EDB6147C09AED243C1F7FAD25",        
    "aimLink": {
      "@id": "AE067F7EDB6147C09AED243C1F7FAD25",
      "@DisplayText": "5100010654120001
    }
  }
},
{
  "@IL1": "Yes",
  "@Name": "Rubber",     
  "Item": [
    {
      "@ItemType": "Rubber",
      "@ItemGID": "622025629037499394DF092DA16BAB7F",          
      "aimLink": {
        "@id": "622025629037499394DF092DA16BAB7F",
        "@DisplayText": "12345678-1234-123456-7116#01"
      }
    },
    {
      "@ItemType": "Rubber",
      "@ItemGID": "F336F65F8E014E80B84A2312F829493C"
      "aimLink": {
        "@id": "F336F65F8E014E80B84A2312F829493C",
        "@DisplayText": "12345678-1234-123456-7116#14"
      }
    }
  ]
}
 ],


What I have tried:

I tried to adopt Generic approach, but couldn't proceed much.

Thanks,
Divya
Posted
Updated 18-Mar-21 7:31am
v2
Comments
PIEBALDconsult 18-Mar-21 10:35am
   
Where does the file come from? Can you ask the source to make the file consistent?
Divya B Nair 18-Mar-21 13:05pm
   
The file format is correct. I have loaded it in online JSON Editor. I just pasted only the portion where I am facing issue while trying to parse using the below code. Hence please ignore if you see a mismatch in braces.
JObject studentObj = JObject.Parse(jsonString);
var res = JsonConvert.DeserializeObject<general>(jsonString);

This is the error I am getting. It's because ItemList[2].Item contains an array whereas in my C# class of ItemList, I have maintained the property as

[JsonProperty("Item")]
public Item ItemsList
{
get;
set;
}

'Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'JsonGridViewer.Model.Item' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List<t> that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.
Path 'Archive.ItemList[2].Item', line 1, position 2507.'
Richard Deeming 19-Mar-21 5:28am
   
The file format is not "correct", as evidenced by the hoops you've had to jump through to parse it successfully. :)

If the item property can contain a list, it should always contain a list, even if it that list only contains one item. Changing it to an object when there's only one item is absolutely the wrong thing to do.

Whoever produced this file is a sadist who hates the consumers of their API!

1 solution

Solved the issue using SingleValueArrayConverter

public class SingleValueArrayConverter<T> : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }



    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        object retVal = new Object();
        if (reader.TokenType == JsonToken.StartObject)
        {
            T instance = (T)serializer.Deserialize(reader, typeof(T));
            retVal = new List<T>() { instance };
        }
        else if (reader.TokenType == JsonToken.StartArray)
        {
            retVal = serializer.Deserialize(reader, objectType);
        }
        return retVal;
    }

    public override bool CanConvert(Type objectType)
    {
        return false;
    }
}

public class ItemList
{
    public string @IL1 { get; set; }
    public string @Name { get; set; }
    [JsonConverter(typeof(SingleValueArrayConverter<Item>))]
    public List<Item> Item { get; set; }
}
   

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900