Skip to content

JsonSerializer.Serialize an anonymous type, with duplicate nested names throws an unexpected exception #81550

@dbaghdanov

Description

@dbaghdanov

Description

Upgrading my project from .netcore 3.1 to .net6 I came across one of my tests failing due to a change in how JsonSerializer.Serialize will serialize an anonymous type.

Reproduction Steps

var obj = new 
{
  input = new {
    foo = "foo"
  },
  INPUT = new {
    foo = "foo"
  }
};

var json = JsonSerializer.Serialize(obj); // throws an exception

Expected behavior

In .netcore 3.1 the above would have returned:

{"input":{"foo":"bar"},"INPUT":{"foo":"bar"}}

Actual behavior

In .net5+ this exception is thrown instead:

Unhandled exception. System.InvalidOperationException: Members 'input' and 'INPUT' on type '<>f__AnonymousType2`2[<>f__AnonymousType1`1[System.String],<>f__AnonymousType1`1[System.String]]' cannot both bind with parameter 'input' in the deserialization constructor.
   at System.Text.Json.ThrowHelper.ThrowInvalidOperationException_MultiplePropertiesBindToConstructorParameters(Type parentType, String parameterName, String firstMatchName, String secondMatchName)
   at System.Text.Json.Serialization.Metadata.JsonTypeInfo.InitializeConstructorParameters(JsonParameterInfoValues[] jsonParameters, Boolean sourceGenMode)
   at System.Text.Json.Serialization.Metadata.JsonTypeInfo..ctor(Type type, JsonConverter converter, Type runtimeType, JsonSerializerOptions options)
   at System.Text.Json.JsonSerializerOptions.<InitializeForReflectionSerializer>g__CreateJsonTypeInfo|112_0(Type type, JsonSerializerOptions options)
   at System.Text.Json.JsonSerializerOptions.GetClassFromContextOrCreate(Type type)
   at System.Text.Json.JsonSerializerOptions.GetOrAddClass(Type type)
   at System.Text.Json.JsonSerializer.GetTypeInfo(JsonSerializerOptions options, Type runtimeType)
   at System.Text.Json.JsonSerializer.Serialize[TValue](TValue value, JsonSerializerOptions options)

Unhandled exception. System.InvalidOperationException: Members 'input' and 'INPUT' on type '<>f__AnonymousType22[<>f__AnonymousType11[System.String],<>f__AnonymousType1`1[System.String]]' cannot both bind with parameter 'input' in the deserialization constructor.

Regression?

Worked as I expected in .netcore 3.1 but not in .net5+

Known Workarounds

If I were to create a class to represent my anonymous type instead, then I do receive the expected JSON string.

public sealed class Obj
{
    public Input input {get; set;}
    public Input INPUT {get; set;}
}

public sealed class Input
{
    public string foo {get;set;}	
}

And instantiate similar to my anonymous type:

var obj = new Obj()
{
    input = new Input()
    {
        foo="bar"
    }, 
    INPUT = new Input()
    {
        foo="bar"
    }
};

var json = JsonSerializer.Serialize(obj);

I do get my expected JSON string:

{"input":{"foo":"bar"},"INPUT":{"foo":"bar"}}

Configuration

$ dotnet --info
.NET SDK (reflecting any global.json):
 Version:   6.0.405
 Commit:    27ab36058b

Runtime Environment:
 OS Name:     debian
 OS Version:  11
 OS Platform: Linux
 RID:         debian.11-x64
 Base Path:   /usr/share/dotnet/sdk/6.0.405/

global.json file:
  /workspaces/bipsli/global.json

Host:
  Version:      6.0.13
  Architecture: x64
  Commit:       1af80ba017

.NET SDKs installed:
  6.0.405 [/usr/share/dotnet/sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.App 6.0.13 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 6.0.13 [/usr/share/dotnet/shared/Microsoft.NETCore.App]

Other information

I posted this same question to StackOverflow where it was suggested that I open an issue here.
https://stackoverflow.com/questions/75317065/exception-serializing-anonymous-type-to-json-when-nested-property-names-are-the

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-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