Skip to content

A converter that inherits JsonConverter<object> doesn't work on properties of nullable value type #36329

@thomaslevesque

Description

@thomaslevesque

If I create a converter that inherits from JsonConverter<object>, it can be applied to a property of type Int32, but not to a property of type Nullable<Int32>. It throws:

InvalidCastException: Unable to cast object of type 'HexIntegerConverter' to type
'System.Text.Json.Serialization.JsonConverter`1[System.Nullable`1[System.Int32]]'.

Repro (in LinqPad)

void Main()
{
    var foo = new Foo { IntProperty = 123, NullableIntProperty = 456 };
    var fooJson = JsonSerializer.Serialize(foo).Dump();
    JsonSerializer.Deserialize<Foo>(fooJson).Dump();
}

class Foo
{
    [JsonConverter(typeof(HexIntegerConverter))]
    public int IntProperty { get; set; }
    [JsonConverter(typeof(HexIntegerConverter))]
    public int? NullableIntProperty { get; set; }
}

// Serializes an int to an hex string
class HexIntegerConverter : JsonConverter<object>
{
    public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        var s = reader.GetString();
        if (string.IsNullOrEmpty(s))
        {
            if (typeToConvert == typeof(int))
                return 0;
            else
                return null;
        }
        
        return int.Parse(s, System.Globalization.NumberStyles.HexNumber);
    }

    public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options)
    {
        if (value is null)
        {
            writer.WriteNullValue();
        }
        else
        {
            writer.WriteStringValue(((int)value).ToString("x"));
        }
    }

    public override bool CanConvert(Type typeToConvert)
    {
        return typeToConvert == typeof(int) || typeToConvert == typeof(int?);
    }
}

This code throws the exception above. If I remove the converter from the nullable property, it works as expected.

This looks like a bug to me. Why is it trying to cast to a JsonSerializer<int?>? It doesn't do that for the non-nullable property...

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions