4

I'm working with an inconsistent Json that i want to deserialize to .Net class of mine. The problem is that sometime i have an Object and sometime it is an Array. What is the best way to do this? Converter? Below is a snippet of my Json Data

[
{
"@class": "odd",
"td": [
  {
    "@class": "user",
    "@onmouseover": "userInfo('469');",
    "@onmouseout": "userInfo(0);",
    "@onmousemove": "moveSlotInfo();",
    "#text": " AAA"
  },
  {
    "@id": "day-469-2014-04-07",
    "@style": "vertical-align: top;",
    "table": {
      "@class": "ss",
      "@cellspacing": "1",
      "tbody": {
        "tr": {
          "td": {
            "@class": "as",
            "@style": "color: #ffffff; background-color: #4040ff;",
            "@onmouseover": "this.className=(document.week_vs_doctor.activityId.value==-1?'sd':'sp');slotInfo('177935',false);",
            "@onmouseout": "this.className='as';slotInfo(0,false);",
            "@onmousemove": "moveSlotInfo();",
            "#text": "KAVAul"
          }
        }
      }
    }
  }
]
},
{
"@class": "even",
"td": [
  {
    "@class": "user",
    "@onmouseover": "userInfo('262');",
    "@onmouseout": "userInfo(0);",
    "@onmousemove": "moveSlotInfo();",
    "#text": " BBB"
  },
  {
    "@id": "day-262-2014-04-07",
    "@style": "vertical-align: top;",
    "table": {
      "@class": "ss",
      "@cellspacing": "1",
      "tbody": {
        "tr": [
          {
            "td": {
              "@class": "as",
              "@style": "color: #ffffff; background-color: #4040ff;",
              "@onmouseover": "this.className=(document.week_vs_doctor.activityId.value==-1?'sd':'sp');slotInfo('174318',false);",
              "@onmouseout": "this.className='as';slotInfo(0,false);",
              "@onmousemove": "moveSlotInfo();",
              "#text": "KAVA "
            }
          },
          {
            "td": {
              "@class": "as",
              "@style": "color: #000000; background-color: #ffc0c0;",
              "@onmouseover": "this.className=(document.week_vs_doctor.activityId.value==-1?'sd':'sp');slotInfo('174338',false);",
              "@onmouseout": "this.className='as';slotInfo(0,false);",
              "@onmousemove": "moveSlotInfo();",
              "#text": "Dagbak"
            }
          }
        ]
      }
    }
  }
]
}
]

The problem is with the tr object either have Object or Array.

Below is my class snippet

    public class Td2
{
    [JsonProperty("@class")]
    public string TdClass { get; set; }

    [JsonProperty("@style")]
    public string style { get; set; }

    [JsonProperty("@onmouseover")]
    public string onmouseover { get; set; }

    [JsonProperty("@onmouseout")]
    public string onmouseout { get; set; }

    [JsonProperty("@onmousemove")]
    public string onmousemove { get; set; }

    [JsonProperty("#text")]
    public string text { get; set; }
}

public class Tr2
{
    public Td2 td { get; set; }
}

public class Tbody2
{
    [JsonProperty]
    [JsonConverter(typeof(ScheduleJsonConverter<Tr2>))]
    public List<Tr2> tr { get; set; }
}

public class Table
{
    [JsonProperty("@cellspacing")]
    public string cellspacing { get; set; }

    public Tbody2 tbody { get; set; }

    [JsonProperty("@class")]
    public string tClass { get; set; }
}
3
  • Include a relevant snippet of (and/or highlight) the "inconsistency". Don't make it hard. Commented Apr 13, 2014 at 22:45
  • I assume this person is having problems with the Tr element. In the JSON it shows a single object. However, a table can have more than one row. Commented Apr 13, 2014 at 22:51
  • @user2864740 If you look at the Json snippet and the text below it "The problem is with the tr object either have Object or Array." you will see it is not hard ;) Commented Apr 14, 2014 at 16:31

1 Answer 1

4

I got this converter from somewhere and it was in one of my projects. I would love to give credit. I will try to search for the post. However, this should fix your problem.

EDIT: AH found it: JSON.NET Deserialize objects within object / array of objects

add this Attribute to the class that may be a single object or an array of objects. like so:

public class Tbody2
{
     [JsonProperty]
     [JsonConverter(typeof (ObjectToArrayConverter<Tr2>))]
     public List<Tr2> tr { get; set; }
 }

The converter will populate the array with a single element if the JSON is just a single element and not an array. Otherwise it will deserialize to a list.

public class ObjectToArrayConverter<T> : CustomCreationConverter<List<T>> where T : new()
{
    public override List<T> Create(Type objectType)
    {
        return new List<T>();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var target = new List<T>();

        try
        {
            // Load JObject from stream
            var jArray = JArray.Load(reader);

            // Populate the object properties
            serializer.Populate(jArray.CreateReader(), target);
        }
        catch (JsonReaderException)
        {
            // Handle case when object is not an array...

            // Load JObject from stream
            var jObject = JObject.Load(reader);

            // Create target object based on JObject
            var t = new T();

            // Populate the object properties
            serializer.Populate(jObject.CreateReader(), t);

            target.Add(t);
        }

        return target;
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks bro, tho i had to change your code and instead of Try and Catch which will produce to much Exceptions to handle, i used If and Else using reader.TokenType. It is much much faster. If you want i will post my code so anyone can get some help ;)
yeah good call. I just copy and pasted from the other post into my project. I think i will do that.
I know this is a bit late, but bless you, and all who follow in your line!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.