skip to Main Content

in my .NET 5 application I deserialize data using the System.Text.Json functions. This works for the most part.
Except for one field in the received JSON document, which can contain a number array, a string array or a single string (without array).

I can handle the first two cases by defining the field in my target type as List<dynamic>. But if the third case occurs, the standalone string, an exception is thrown.

How can I achieve that this third case is also handled without exception. I would prefer to get a single element in my list. Is this possible?

This are 3 possible values in JSON:

{
  "range": [
    0,
    100
  ]
}

{
  "range": [
    "yes",
    "no"
  ]
}

{
  "range": "n/a"
}

2

Answers


  1. You will need either to write custom converter or dive into dynamic deserialization for example with JsonDocument:

    // .NET 7 feature here - raw string literals:
    var jsons = new[]
    {
        """
        {
          "range": [
            0,
            100
          ]
        }
        """,
        """
        {
          "range": [
            "yes",
            "no"
          ]
        }
        """,
        """
        {
          "range": "n/a"
        }
        """
    };
    
    foreach (var jsonStr in jsons)
    {
        using var jd = JsonDocument.Parse(jsonStr);
        var jsonElement = jd.RootElement.GetProperty("range");
        switch (jsonElement.ValueKind)
        {
            case JsonValueKind.Array:
                var array = jsonElement.Deserialize<object[]>();
                Console.WriteLine(array.Length);
                break;
            case JsonValueKind.String:
                Console.WriteLine(jsonElement.GetString());
                break;
        }
    }
    

    Demo @sharplab.io

    Login or Signup to reply.
  2. you can try this custom converter

    var testRange = System.Text.Json.JsonSerializer.Deserialize<TestRange>(json);
    
    public class TestRange
    {
        [System.Text.Json.Serialization.JsonConverter(typeof(ToListJsonConverter))]
        public List<object>? range { get; set; }
    }
    
    public class ToListJsonConverter : System.Text.Json.Serialization.JsonConverter<List<object>>
    {
        public override List<object> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            if (reader.TokenType == JsonTokenType.StartArray)
            {
                var arr = System.Text.Json.JsonSerializer.Deserialize<List<object>>(ref reader, options);
                if (arr is null) return default;
                      else  return  arr;
            }
            else if (reader.TokenType == JsonTokenType.String) return new List<object> { reader.GetString() };
            return default;
        }
    
        public override void Write(Utf8JsonWriter writer, List<object> value, JsonSerializerOptions options)
        {
            throw new NotImplementedException();
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search