1

I have a json file which has either of the following formats:

  1. Sample 1:
{
  "MyOrders": [
    {
      "order": "my order1",
      "url": "tt"
    }
  ]
}

Sample 2:

{
  "MyOrders": [
    [
      {
        "order": "my order 1",
        "url": "ddfdfd"
      },
      {
        "order": "order 2",
        "url": "asdfwe"
      }
     ],
     [
      {
        "order": "my order 3",
        "url": "ertrt"
      },
      {
        "order": "my order 4",
        "url": "werwe"
      }
    ]
  ]
}

I have the following code:

InputItems root = JsonConvert.DeserializeObject<InputItems>(myJsonText);

And I have the following classes:

public class InputItems 
    {
            [JsonProperty("MyOrders")]
            public List<Order> objects { get; set; }
        
    }

    public class Order
    {

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

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

}

But it works just for the first case. How can I improve it to also cover the second sample format?

Thanks in advance.

3
  • You don't have to quote your JSON (the > prefix) by the way Commented Sep 18, 2020 at 10:42
  • 3
    If you look closely at your "sample 2" JSON, you'll note that you don't have an array of orders - you have an array or arrays of orders. Therefore in .NET that would be a List of List of Order, not just a List of Order. As for how to deserialize both of them with the same code, I'd probably create a JsonConverter to apply to List<Order> and then have it work out if the JToken is a JObject or JArray and deserialize accordingly. I'll help later if i have time. Commented Sep 18, 2020 at 10:43
  • Can be helpful: stackoverflow.com/questions/18994685/… Commented Sep 18, 2020 at 11:28

1 Answer 1

2

I've written a converter that should help you:

public class SingleArrayOrNestedConverter<TItemType> : JsonConverter<List<TItemType>>
{
    public override List<TItemType> ReadJson(JsonReader reader, Type objectType, List<TItemType> existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        // Read the object as JSON
        var token = JToken.ReadFrom(reader);
        if (token is JObject) // it's just a lone object, so wrap it in a list and return it
        {
            return new List<TItemType>() { token.ToObject<TItemType>(serializer) };
        }
        else if (token is JArray arrayOfObjects) // it's an array of objects, so let's loop through
        {
            var result = new List<TItemType>();
            foreach (var item in arrayOfObjects)
            {
                if (item is JObject) // the nested item is an object, so let's add it to the list
                {
                    result.Add(item.ToObject<TItemType>(serializer));
                }
                else if (item is JArray nestedArrayOfObjects) // the nested item is an array, so let's loop through it
                {
                    foreach (var nestedItem in nestedArrayOfObjects)
                    {
                        // this will throw an exception if nestedItem doesn't represent an object
                        result.Add(nestedItem.ToObject<TItemType>(serializer));
                    }
                }
            }
            return result;
        }
        return null;
    }

    // we can't use this code for serializing so make sure JSON.NET doesn't try
    public override bool CanWrite => false;

    public override void WriteJson(JsonWriter writer, List<TItemType> value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

This will work with the following JSON samples.

Sample 1:

{
    "MyOrders": [{
            "order": "my order1",
            "url": "tt"
        }
    ]
}

Sample 2:

{
    "MyOrders": [
        [{
                "order": "my order1",
                "url": "tt"
            }
        ]]
}

Sample 3:

{
    "MyOrders": {
        "order": "my order1",
        "url": "tt"
    }
}

Sample 4:

{
    "MyOrders": [
        [{
                "order": "my order1",
                "url": "tt"
            }
        ], {
            "order": "my order1",
            "url": "tt"
        }
    ]
}

To apply it to your code, you'll need to use the JsonConverterAttribute:

[JsonConverter(typeof(SingleArrayOrNestedConverter<Order>))]

Which looks like this:

public class InputItems
{
    [JsonProperty("MyOrders")]
    [JsonConverter(typeof(SingleArrayOrNestedConverter<Order>))]
    public List<Order> objects { get; set; }
}
Sign up to request clarification or add additional context in comments.

Comments

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.