Skip to content

[JsonSerializer] Relax restrictions on ctor param type to immutable property type matching where reasonable #44428

@JSkimming

Description

@JSkimming

Description

I'm trying to deserialise an object from a json string. In this case the constructor allows a nullable value type as the parameter, setting a non-null property (defaulting if null).

I expect (since it is the behaviour with Newtonsoft.Json) the serializer to handle compatible constructor and bound value type properties (or fields) where the only difference is one is nullable.

The following demonstrates the issue:

public class Example
{
    public Example(Guid? aGuid) => AGuid = aGuid ?? Guid.Empty;
    public Guid AGuid { get; }
}

Example original = new Example(Guid.NewGuid());

// Works with Newtonsoft.Json.
string withJsonNet = JsonConvert.SerializeObject(original);
JsonConvert.DeserializeObject<Example>(withJsonNet);

// Fails with System.Text.Json.
string withSystemTextJson = System.Text.Json.JsonSerializer.Serialize(original);
System.Text.Json.JsonSerializer.Deserialize<Example>(withSystemTextJson);

An InvalidOperationException is thrown from the method System.Text.Json.JsonSerializer.Deserialize :

System.InvalidOperationException: Each parameter in constructor 'Void .ctor(System.Nullable`1[System.Guid])' on type 'Example' must bind to an object property or field on deserialization. Each parameter name must match with a property or field on the object. The match can be case-insensitive.

Configuration

I'm building an ASP.NET Core app targeting netcoreapp3.1, and using version 5.0.0-rc.2.20475.5 of System.Text.Json. I'm also using version 12.0.3 of Newtonsoft.Json.

Other information

Stack Trace:

System.InvalidOperationException: Each parameter in constructor 'Void .ctor(System.Nullable`1[System.Guid])' on type 'Example' must bind to an object property or field on deserialization. Each parameter name must match with a property or field on the object. The match can be case-insensitive.
   at System.Text.Json.ThrowHelper.ThrowInvalidOperationException_ConstructorParameterIncompleteBinding(ConstructorInfo constructorInfo, Type parentType)
   at System.Text.Json.Serialization.Converters.ObjectWithParameterizedConstructorConverter`1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
   at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
   at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
   at System.Text.Json.JsonSerializer.ReadCore[TValue](JsonConverter jsonConverter, Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
   at System.Text.Json.JsonSerializer.ReadCore[TValue](Utf8JsonReader& reader, Type returnType, JsonSerializerOptions options)
   at System.Text.Json.JsonSerializer.Deserialize[TValue](String json, Type returnType, JsonSerializerOptions options)
   at System.Text.Json.JsonSerializer.Deserialize[TValue](String json, JsonSerializerOptions options)
   at <custom code>

Metadata

Metadata

Assignees

No one assigned

    Labels

    Team:Librariesapi-suggestionEarly API idea and discussion, it is NOT ready for implementationarea-System.Text.JsonenhancementProduct code improvement that does NOT require public API changes/additions

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions