Skip to content

Improve error message for dictionary key converters not implementing ReadAsPropertyName/WriteAsPropertyName. #93406

@bitbonk

Description

@bitbonk

Description

When I serialize an object that contains a property of type Dictionary<TKey, TValue> and TKey is a custom class, I get a NotSupportedException, even if there is a JSON converter for this.

JsonSerializer.Serialize(
    new Custom
    {
        Dict = new Dictionary<CustomKey, string>
        {
            [new CustomKey {Value1 = "one", Value2 = "two"}] = "three",
            [new CustomKey {Value1 = "four", Value2 = "five"}] = "six"
        }});
class Custom
{
    public Dictionary<CustomKey, string> Dict { get; set; }
}

[JsonConverter(typeof(CustomKeyJsonConverter))]
class CustomKey
{
    public string Value1 { get; set; }
    public string Value2 { get; set; }

    public static CustomKey Parse(string text)
    {
        var values = text.Split("-");
        return new CustomKey {Value1 = values[0], Value2 = values[1]};
    }

    public override string ToString()
    {
        return $"{this.Value1}-{this.Value2}";
    }
}

class CustomKeyJsonConverter : JsonConverter<CustomKey>
{
    public override CustomKey? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        return CustomKey.Parse(reader.GetString());
    }

    public override void Write(Utf8JsonWriter writer, CustomKey value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(value.ToString());
    }
}

Reproduction Steps

see above

Expected behavior

The serialization (and deserialization) should succeed if there is a JSON converter for the key.

Actual behavior

The following NotSupportedException exception is thrown

System.NotSupportedException
The type 'JsonTest.CustomKey' is not a supported dictionary key using converter of type 'JsonTtest.CustomKeyJsonConverter'. The unsupported member type is located on type 'System.String'. Path: $.Dict.
   at System.Text.Json.ThrowHelper.ThrowNotSupportedException(WriteStack& state, NotSupportedException ex)
   at System.Text.Json.Serialization.JsonConverter`1.WriteCore(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1.Serialize(Utf8JsonWriter writer, T& rootValue, Object rootValueBoxed)
   at System.Text.Json.JsonSerializer.WriteString[TValue](TValue& value, JsonTypeInfo`1 jsonTypeInfo)
   at System.Text.Json.JsonSerializer.Serialize[TValue](TValue value, JsonSerializerOptions options)

Regression?

The same behavior is in .NET 6, 7 and 8, so it probably not a regression.

Known Workarounds

Write a custom JSON for the whole Dictionary<CustomKey, string> type.

Configuration

Windows 11, ,NET SDK 8.0.100-rc.2.23502.2

Other information

No response

Metadata

Metadata

Assignees

Labels

area-System.Text.JsonenhancementProduct code improvement that does NOT require public API changes/additionshelp wanted[up-for-grabs] Good issue for external contributors

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions