1

I work with devices that send their configuration in JSON:

{
    "A": {
        "AA": "1,customconverter,2019",
        "AB": {
            "ABA": "google.com",
            "ABB": 25.0
        }
    },
    "B": {
        "BA": 100
    }
}

Corresponding .NET classes:

class AA
{
    public int X { get; set; }

    public string Y { get; set; }

    public DateTime Z { get; set; }
}

class AB
{
    public string ABA { get; set; }

    public double? ABB { get; set; }
}

class A
{
    [JsonConverter(typeof(MyCustomJsonConverter))]
    public AA AA { get; set; }

    public AB AB { get; set; }
}

enum MyEnum
{
    Unknown = 0,
    Wow = 1,
    Lol = 2
}

class B
{
    public MyEnum BA { get; set; }
}

class Config
{
    public A A { get; set; }

    public B B { get; set; }
}

It may happen that some particular device doesn't have e.g. AB setting and instead of sending ordinary "null" or just omitting that field it sends "?" instead:

{
    "A": {
        "AA": "1,customconverter,2019",
        "AB": "?"
    },
    "B": {
        "BA": 100
    }
}

It can happen for any field regardless if it's a string or not.

Config class is huge and deep. I use custom converters a lot. What I need is some approach that will convert this question mark "?" to default value if it's value type or null if it's nullable/class/reference type.

I thought about some global JsonConverter, but it seems I can't just make one JsonConverter applied for every possible type, becasue it has infinite recursion problems. It is easy to avoid it if converter is designed just for one type: https://stackoverflow.com/a/36116462/6440521 but how to avoid it if converter is applied for many types / global? Also I can fallback to some default behavior from custom JsonConverter: https://stackoverflow.com/a/35590069/6440521 but how to fallback to other converter (e.g. specified in property attribute) based on objectType (keeping in mind we're in global JsonConverter that handles many types)?

What is the best approach to do this in Json.NET?

EDIT: Currently my workaround is to replace every occurence of "?" with null before deserialization and use nullables everywhere (for value types)

  • 1) Is `"?"` ever a **valid** value, e.g. for a string? 2) *Config class is huge and deep. I use custom converters a lot.* - do you have control over those converters? Can you modify them? 3) Is `"?"` only ever used as a default value for a JSON object, or is it sometimes used as a default value for a JSON array? For a JSON primitive? – dbc Jan 01 '19 at 21:47
  • @dbc 1) It probably shouldn't be (documentation for the device doesn't say anything about it though) 2) Yes. I could handle it in every custom JsonConverter and probably use some inheritance to share code, but there are still a lot of objects and fields that I don't use custom converters and Json.NET throws exceptions for them when there is "?" 3) It may be an array or even elements in array e.g. [1,2,"?",4,5,"?"]. It can also be primitive type. Currently my workaround is to replace every occurence of "?" with null before deserialization and use nullables everywhere –  Jan 01 '19 at 23:10
  • Sounds like you first need to get a better understanding of the configuration model before you attempt to deserialize it into .net objects. Perhaps working with dynamics can be a solution but if you don’t know what the model can possibly throw at you, it’s a bit of a gamble each time you attempt to process the data – Robbert Draaisma Jan 01 '19 at 23:47
  • @RobbertDraaisma Actually config model deserializes fine when device has all the settings. The hard part is handling odd behaviour when device misses something and sends "?" instead of null - this behaviour is documented –  Jan 02 '19 at 15:05
  • @dbc I evaluated again and some settings on the device can be set manually to whatever value, so it is possible (but unlikely) that someone can change *string* value to "?", and my fix with replacing all "?" with null is broken. I guess I need to do this substitution only for non-string fields –  Jan 02 '19 at 15:08
  • The problemen here is that it seems to me the configuration model depends on the untyped behavior of JavaScript objects. .net classes don’t have that kind of flexibility. It’s one of the reasons they came up with dynamics see https://www.newtonsoft.com/json/help/html/QueryJsonDynamic.htm no need to design classes that will never match the original model – Robbert Draaisma Jan 02 '19 at 21:26

0 Answers0