1

I have a Json that looks as this:

{
    "id": "1367",
    "title": "ticket sample",
    "custom_fields": {
        "13084": {
            "E0D4ED43": "South"
        },
        "13085": {
            "F19DF0D6": "Atlanta"
        },
        "13089": {
            "AF0EC62F": "Peter Johnson"
        }
    }
}

And to parse it, my class uses nested Dictionaries:

class incident
    {
        public string id { get; set; }
        public string title { get; set; }
        public Dictionary<int, Dictionary<string, string>> custom_fields { get; set; }
    }

This works like a charme, until I've discovered that the custom fields are not always the same, for example I could receive:

{
    "id": "1367",
    "title": "ticket sample",
    "custom_fields": {
        "13084": {
            "E0D4ED43": "South"
        },
        "13085": {
            "F19DF0D6": "Atlanta"
        },
        "13086": "SAP",
        "13088": {
            "AE3ED01A": "Commercial"
        }
    }
}

If you look at the custom field "13086", it doesn't contains another object (it's just a string), so when I try to parse with the previous class it fails.

Those are examples of two different responses, but the keys received change a lot (that's why I used Dictionaries because I don't know how many and which will be received for each ticket)

  • You're going to need to use a custom converter. Do you know that the custom field values are always strings or dictionaries of strings, or could they be *anything*? – dbc Mar 25 '21 at 14:34
  • @dbc by now I've only seen strings or dictionaries of strings, but you've just scared me! I thinks it could be anything, even arrays... – Hernan Romero Mar 25 '21 at 14:49
  • @HernanRomero I think you should use Dictionary – Dilshod K Mar 25 '21 at 14:51
  • @DilshodK You get a non-deserialized JToken then, how you'll handle it?. -- It's not *complicated* to write a JsonConverter to deserialize these objects, whatever they are in input. Just decide to what to deserialize to. The point is if you need to serialize back and serialize back to what. If serialize all back to a `Dictionary` could be a thing, then it's simple. The link posted in the first comment can be modified to handle this use-case. – Jimi Mar 25 '21 at 15:00
  • 1
    @HernanRomero, you can serialize and deserialize to class incident { public string id { get; set; } public string title { get; set; } public Dictionary custom_fields { get; set; } } – Dilshod K Mar 25 '21 at 15:06
  • @DilshodK I've just tested to deserialize using Dictionary and it works! Now I'm trying to figure out how to check the class of the object and re-deserialize it in an appropiate way. Thank you very much for the guide – Hernan Romero Mar 25 '21 at 15:37
  • If you deserialize to a `Dictionary` then the actual, concrete types used for the values will be subclasses of `JToken`. If you want to convert those Json.NET-specific types to plain .Net types like `Dictionary`, `List` and so on, see [How do I use JSON.NET to deserialize into nested/recursive Dictionary and List?](https://stackoverflow.com/a/19140420/3744182). – dbc Mar 25 '21 at 15:43

1 Answers1

0

Thank you all guys for your comments. Thanks to them I figured it out and found a solution that works for me.

Basically, I've used the "Dictionary<int, object>" proposed by @DilshodK and then I check for the type of the object. If the object is a JObject I re-deserialize with another Dictionary, if not I use the original value.

class incident_custom
    {
        public string id{ get; set; }
        public string title { get; set; }
        public Dictionary<int, object> custom_fields { get; set; }
    }
incident_custom item = JsonConvert.DeserializeObject<incident_custom>(responseBody);

Console.WriteLine(item.title);

foreach (var field in item.custom_fields)
{
    if (field.Value.GetType() == typeof(Newtonsoft.Json.Linq.JObject))
    {

        Dictionary<string, object> values = JsonConvert.DeserializeObject<Dictionary<string, object>>(field.Value.ToString());

        foreach (var value in values)
        {
            Console.WriteLine(field.Key + " - " + value.Value);
        }
    }
    else
    {
        Console.WriteLine(field.Key + " - " + field.Value);
    }
}