Reputation: 117
I have a json
file which has either of the following formats:
{
"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.
Upvotes: 1
Views: 255
Reputation: 38880
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; }
}
Upvotes: 2