0

I am trying to implement a JsonConverter that will work when deserializing a single object as well as when that object is in a list. It works fine when using with a single object but not when the Json contains a array of the objects.

Here is the class:

public class APIEntity
{
    [JsonPropertyName("id")]
    public int Id { get; set; }

    [JsonPropertyName("type")]
    public string Type { get; set; }

    [JsonConverter(typeof(MyCustomClassPropertiesJsonConverter))]
    [JsonPropertyName("properties")]
    public Dictionary<string, string> Properties { get; set; }
}

Here is the JsonConverter class:

public class MyCustomClassPropertiesJsonConverter : JsonConverter<Dictionary<string,string>>
{
    public override Dictionary<string, string> Read(
            ref Utf8JsonReader reader,
            Type typeToConvert,
            JsonSerializerOptions options)
    {
        if (reader.TokenType != JsonTokenType.String)
        {
            throw new JsonException();
        }

        var dictionary = new Dictionary<string, string>();

        // Get the Json value.
        string propertiesValue = reader.GetString();

        if(string.IsNullOrEmpty(propertiesValue))
        {
            throw new JsonException();
        }

        var propertiesItems = propertiesValue.Split('|', StringSplitOptions.RemoveEmptyEntries);

        foreach (var propertyItem in propertiesItems)
        {
            var item = propertyItem.Split('=');
            dictionary.Add(item[0], item[1]);
        }

        return dictionary;
    }

    public override void Write(
            Utf8JsonWriter writer,
            Dictionary<string, string> dictionary,
            JsonSerializerOptions options)
    {
        writer.WriteStartObject();

        writer.WritePropertyName("properties");

        string propertiesValue = "";
        foreach ((string key, string value) in dictionary)
        {
            propertiesValue += $"{key}={value}|";
        }
        propertiesValue.Trim('|');
        
        writer.WriteStringValue(propertiesValue);

        writer.WriteEndObject();
    }
}

The Json looks like this for a list:

[
    {
        "id": 12706609,
        "name": "Object 1",
        "type": "Type1",
        "properties": "prop1=value1|prop2=value2"
    },
    {
        "id": 12706631,
        "name": "Object 2",
        "type": "Type1",
        "properties": "prop1=value1|prop2=value2"
    }
]

The calling code looks like this single object:

var response = await client.GetAsync(@"https://service.domain.com/getSinlge?id=12715188");
var entity = await response.Content.ReadFromJsonAsync<APIEntity>();

And like this for a list:

var response = await ient.GetAsync(@"https://service.domain.com/getLIst?id=12715188");
var entityList = await response.Content.ReadFromJsonAsync<List<APIEntity>>();

Any help would be appreciated

dbc
  • 104,963
  • 20
  • 228
  • 340
  • The problem is somewhere else in your code or with the data you receive from the server. It's not the JsonConverter's Read method. It's not the ReadFromJsonAsync method either, which internally uses System.Text.Json. And System.Text.Json has no problem deserializing a Listwhile accounting for the \[JsonConverter\] attribute. Proof: https://dotnetfiddle.net/Eg3n0s –  Sep 14 '22 at 21:43
  • Thanks @MySkullCaveIsADarkPlace. You were right on in that it was elsewhere in my code. I am using HttpClient and HttpResponseMessage and was calling ReadAsAsync instead of ReadFromJsonAsync on the Content property. I assume that it needed the HttpContentJsonExtension method to use the JsonConverter. It was not working as I expected in my test code for a list because my test code was getting an empty list back because of a bad query string param. Nothing like someone else looking at your code to make you find your own bugs! – Gordon Gudmundson Sep 15 '22 at 15:23

0 Answers0