Search code examples
c#jsondeserializationsystem.text.json

Deserialize field with array or string


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"
}

Solution

  • 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();
        }
    }