0

I have this JSON structure:

[
  {
    "key1": "value",
    "key2": "value",
    "key3": "TYPE_ONE",
    "extraData": {
      "key4": "value",
      "key5": "value",
      "key6": {
        "key7": {
          "key8": "value",
          "key9": "value",
          "key10": "value"
        }
      }
    }
  },
  {
    "key1": "value",
    "key2": "value",
    "key3": "TYPE_TWO",
    "extraData": {
      "key4": "value",
      "key5": "value",
      "key6": {
        "key7": [
          {
            "key8": "value",
            "key9": "value",
            "key10": "value"
          },
          {
            "key8": "value1",
            "key9": "value1",
            "key10": "value1"
          },
          {
            "key8": "value2",
            "key9": "value2",
            "key10": "value2"
          }
        ]
      }
    }
  }
]

I'm trying to deserialize it with using Newtonsoft.Json; in C#. JSON has two structures.
1. CASE -> when "key3": "TYPE_ONE", then key7 is object.
2. CASE -> when "key3": "TYPE_TWO", Then key7 is array.
If in class

public class key6
{
    public key7 key7Item { get; set; }
}

key7Item is set as object works only if i get all object from response that are "key3": "TYPE_ONE"
If i set key7Item as List then works only if all items from response are "key3": "TYPE_TWO".

Can i configure Newtonsoft parser to parse array if it got array or object if it got object?

zonelsk
  • 235
  • 1
  • 5
  • 14
  • If you have two JSON structures you need two classes to represent them. Otherwise, use the same structure regardless of `key3` and just use a single item inside the array. – Camilo Terevinto Dec 18 '17 at 12:15
  • @CamiloTerevinto How can I tell parser to parse key7 allways as array, even if is returned as object? Or, in other case, how can I tell parser to use different classes depending on key3? – zonelsk Dec 18 '17 at 12:22
  • Yes, you can use a `SingleOrArrayConverter` as shown in [How to handle both a single item and an array for the same property using JSON.net](https://stackoverflow.com/q/18994685/10263). Use `key7` as `T` instead of `string`. – Brian Rogers Dec 18 '17 at 17:58

1 Answers1

1

Short answer - don't do this if you can possibly avoid it. You'll save yourself lots of complexity by giving the array a different key name.

Long answer, you can do it, but it's painful. If anyone knows how to do with without re-serializing the j-objects that are generated (i.e. keeping the json alongside the deserialized objects), I'd love to know:

private static readonly string Json = "[\r\n  {\r\n    \"key1\": \"value\",\r\n    \"key2\": \"value\",\r\n    \"key3\": \"TYPE_ONE\",\r\n    \"extraData\": {\r\n      \"key4\": \"value\",\r\n      \"key5\": \"value\",\r\n      \"key6\": {\r\n        \"key7\": {\r\n          \"key8\": \"value\",\r\n          \"key9\": \"value\",\r\n          \"key10\": \"value\"\r\n        }\r\n      }\r\n    }\r\n  },\r\n  {\r\n    \"key1\": \"value\",\r\n    \"key2\": \"value\",\r\n    \"key3\": \"TYPE_TWO\",\r\n    \"extraData\": {\r\n      \"key4\": \"value\",\r\n      \"key5\": \"value\",\r\n      \"key6\": {\r\n        \"key7\": [\r\n          {\r\n            \"key8\": \"value\",\r\n            \"key9\": \"value\",\r\n            \"key10\": \"value\"\r\n          },\r\n          {\r\n            \"key8\": \"value1\",\r\n            \"key9\": \"value1\",\r\n            \"key10\": \"value1\"\r\n          },\r\n          {\r\n            \"key8\": \"value2\",\r\n            \"key9\": \"value2\",\r\n            \"key10\": \"value2\"\r\n          }\r\n        ]\r\n      }\r\n    }\r\n  }\r\n]";

private static void Deserialize()
{
    var switchers = JsonConvert.DeserializeObject<JObject[]>(Json);
    var deserializedType1List = new List<TargetClass<Key6Type1>>();
    var deserializedType2List = new List<TargetClass<Key6Type2>>();
    foreach (var switcher in switchers)
    {
        if (switcher["key3"].Value<string>() == "TYPE_ONE")
        {
            deserializedType1List.Add(JsonConvert.DeserializeObject<TargetClass<Key6Type1>>(JsonConvert.SerializeObject(switcher)));
        }
        else
        {
            deserializedType2List.Add(JsonConvert.DeserializeObject<TargetClass<Key6Type2>>(JsonConvert.SerializeObject(switcher)));
        }
    }

    //Do something with the objects...
}

private class TargetClass<TKey6Type>
{
    public string key1 { get; set; }

    public string key2 { get; set; }

    public string key3 { get; set; }

    public ExtraData<TKey6Type> extraData { get; set; }
}

private class ExtraData<TKey6Type>
{
    public string key4 { get; set; }

    public string key5 { get; set; }

    public TKey6Type key6 { get; set; }
}

private class Key6Type2
{
    public Key7[] key7 { get; set; }
}

private class Key6Type1
{
    public Key7 key7 { get; set; }
}

private class Key7
{
    public string key8 { get; set; }
    public string key9 { get; set; }
    public string key10 { get; set; }
}
Adam Brown
  • 1,667
  • 7
  • 9