0

I need to deserialize dynamic JSON text that can represent either System.Collections.Generic.Dictionary<string, T> or System.Collections.Generic.List< T>. I suppose I have to write custom converter but I'm not sure about how it should look like properly. I'm using .NET5's System.Text.Json.

Sample JSON for dictionary type (sent almost all the time):

{
"1":
    {
       "13346964555":
          {
              "data1":1,
              "data2":2
          },
        "13346964556":
          {
              "data1":1,
              "data2":2
          },
     }
}

Sample JSON for list type (rare, needs to be converted into dictionary with empty string keys):

{
"1": [
     {
        "data1":1,
        "data2":2
     },
     {
        "data1":1,
        "data2":2
     }
   ]
}

On the other side, converting from normal dictionary to list of its values is acceptable as well, since I don't need keys at all currently.

Brian Rogers
  • 125,747
  • 31
  • 299
  • 300
Alex xelA
  • 85
  • 9
  • Why is there a dynamic JSON? It's wrong. Sometimes you get stuck, but I'm curious what's happening here where you don't know what shape of data you are getting? – Austin T French Jan 05 '21 at 15:18
  • I receive JSON object of a type Dictionary>. it's okay but the latest item in this dictionary is List instead of Dictionary, it simply arrives in format of array (as you see in my samples) instead of dictionary. I do not control how JSON is produced so everything I can do is to adopt to this strange "feature" of the sender. – Alex xelA Jan 05 '21 at 15:36

1 Answers1

0

ended up with this converter, from Dictionary to List, based on another example. seems to work fine in my case. feel free to discuss if something is wrong here. note that I only need to convert specific dictionary type, so no need for converters' factory here.

public class DictionaryToListConverter : JsonConverter<List<type>>
{
    public override bool CanConvert(Type typeToConvert)
    {
        return typeof(List<type>) == typeToConvert;
    }

    public override List<type> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        bool is_array = reader.TokenType == JsonTokenType.StartArray;
        bool is_dictionary = reader.TokenType == JsonTokenType.StartObject;

        if (is_array || is_dictionary)
        {
            var list = new List<type>();

            while (reader.Read())
            {
                if ((is_array && reader.TokenType == JsonTokenType.EndArray) || (is_dictionary && reader.TokenType == JsonTokenType.EndObject))
                    return list;

                if (is_dictionary)
                {
                    if (reader.TokenType != JsonTokenType.PropertyName)
                        throw new JsonException();

                    reader.Read(); // skip the key and move to value.
                }

                list.Add(JsonSerializer.Deserialize<type>(ref reader));
            }
        }

        throw new JsonException();
    }

    public override void Write(Utf8JsonWriter writer, List<type> value, JsonSerializerOptions options)
    {
        // ...
    }
}
Alex xelA
  • 85
  • 9