0

I'm using API, where the response is represeted by the multi-layer nested JSON.

{
    "name": "Example",
    "settings": {
        "exampleOne": "value",
        "exampleTwo": 100,
        "exampleThree": {
            "subexampleOne": "value",
            "subexampleTwo": "value"
        },
        "arrayProperty": [
            {"subexampleOne": "value"},
            {"subexampleTwo": "value"}
        ]
    }
}

Settings is supporting simple properties (numbers, strings, etc), complex types with inner properties or arrays of properties. I cannot predict how many levels the JSON will have.

How to model the proper DTO for such JSON's? Shoud I use just string, JObject, or maybe completely different approach?

WymyslonyNick
  • 117
  • 3
  • 19
  • All of the above. We can't guess without knowing what the actual contents may be. Perhaps you can create a single self-referencing type, perhaps not. Perhaps you only need to do so for one of the properties, perhaps not. Most JSON documents are nested. All are dictionaries and arrays. A *realistic* example would be more useful – Panagiotis Kanavos Jul 30 '21 at 09:13
  • A JObject matches *any* object, so in the worst case scenario you could parse the entire document into a single JObject and inspect its elements one by one. Or use a JsonDocument to handle both objects and arrays. If the document schema is completely arbitrary you may have no other option. This is rarely the case though. – Panagiotis Kanavos Jul 30 '21 at 09:16
  • @PanagiotisKanavos , the JSON is representing device configuration. In general the documentation says the settings are dynamic and the structure depends on the device. The only one thing what I can predict it is a fact the the settings-node is required. But what exactly will be placed inside the settings - I have no idea. – WymyslonyNick Jul 30 '21 at 09:36
  • 2
    How are you going to read then if you don't know what to expect? In any case, if the content is completely dynamic you should use JObject. It's far more likely that the document has some fixed parts at the top level along with the dynamic settings. You can use a DTO with properties for the fixed settings and `dynamic` , `JObject` or `JArray` for the dynamic part. If the only fixed parts are `name` and `settings` though, it may not be worth it. – Panagiotis Kanavos Jul 30 '21 at 09:38
  • @PanagiotisKanavos, of course you are right - under the settings I have some fixed properties like name, device id, etc. I presented here the part which is problematic from my perspective - dynamic settings. – WymyslonyNick Jul 30 '21 at 09:53
  • @WymyslonyNick - if `"settings"` has some combination of fixed and variable properties use a `[JsonExtensionData] public Dictionary { get; set; }` property. See: [How to serialize a Dictionary as part of its parent object using Json.Net](https://stackoverflow.com/q/14893614/3744182) (for Json.NET) and [Is it possible to catch somehow the remainder of JSON data that didn't match any POCO properties while deserializing?](https://stackoverflow.com/q/63227109/3744182) (for System.Text.Json). – dbc Jul 30 '21 at 13:12

1 Answers1

1

Since the json is dynamic, I would recommend using Jobject and JToken to parse the JSON and take decision based on the JTokenType

var jsonString = File.ReadAllText("json1.json");
var jObj = JObject.Parse(jsonString);
foreach (var x in jObj)
{
    string name = x.Key;
    JToken value = x.Value;
    if (name == "settings")
    {
        foreach (var y in (JObject)x.Value)
        {
            string name1 = y.Key;
            JToken value1 = y.Value;
            switch (value1.Type)
            {
                case JTokenType.String:
                    Console.WriteLine($"it is string {value1}");
                    break;
                case JTokenType.Integer:
                    Console.WriteLine($"it is number {value1}");
                    break;
                case JTokenType.Array:
                    Console.WriteLine($"it is array {value1}");
                    break;
                case JTokenType.Object:
                    Console.WriteLine($"it is object {value1}");
                    break;
                default:
                    Console.WriteLine($"type not defined {value1}");
                    break;
            }
        }
    }
}
Krishna Varma
  • 4,238
  • 2
  • 10
  • 25