Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Serializing type which hides inherited property with both properties ignored throws ArgumentException #66900

Closed
Tracked by #73255
AndersWangRask opened this issue Mar 20, 2022 · 2 comments · Fixed by #87167

Comments

@AndersWangRask
Copy link

AndersWangRask commented Mar 20, 2022

Description

With System.Text.Json when trying to serialize a class that is inheriting from a class and is using the new keyword for a property and the new property and the hidden property return different types that has the same name (e.g. "Class1") and both properties are set to [JsonIgnore] an exception is thrown with the following message:

An item with the same key has already been added. Key: class1

It looks like there are actual two problems:

First that two types cannot have the same name apparently.

Second that it only looks at both types when both properties are set to [JsonIgnore]. All other combinations seems to work.

I have identified the issue in both .Net 6 and .Net 7 Preview 2.

Reproduction Steps

Run following code as a Console app in .Net 6 or 7:

using System.Text.Json.Serialization;

Console.WriteLine("Hello, World!");

MyNamespace.Class2 class2 = new MyNamespace.Class2();

string jsonText;

try
{
    jsonText = System.Text.Json.JsonSerializer.Serialize(class2);
}
catch (Exception ex)
{
    jsonText = "EXCEPTION: " + ex.Message;
}

Console.WriteLine(jsonText);

namespace MyNamespace
{
    public class Class1
    {

    }

    public class Class2 : MyNamespaceBase.Class2
    {
        [JsonIgnore]
        public new Class1 class1 => new Class1();
    }
}

namespace MyNamespaceBase
{
    public class Class1
    {

    }

    public class Class2
    {
        [JsonIgnore]
        public Class1 class1 => new Class1();
    }
}

Expected behavior

Should not throw exception. Should serialize the object.

Actual behavior

Following exception is thrown:

System.ArgumentException: An item with the same key has already been added. Key: class1
   at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior)
   at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
   at System.Text.Json.Serialization.Metadata.JsonTypeInfo.CacheMember(Type declaringType, Type memberType, MemberInfo memberInfo, Boolean isVirtual, Nullable`1 typeNumberHandling, Boolean& propertyOrderSpecified, Dictionary`2& ignoredMembers)
   at System.Text.Json.Serialization.Metadata.JsonTypeInfo..ctor(Type type, JsonConverter converter, Type runtimeType, JsonSerializerOptions options)
   at System.Text.Json.JsonSerializerOptions.<InitializeForReflectionSerializer>g__CreateJsonTypeInfo|120_0(Type type, JsonSerializerOptions options)
   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
   at System.Text.Json.JsonSerializer.GetTypeInfo(JsonSerializerOptions options, Type runtimeType)
   at System.Text.Json.JsonSerializer.Serialize[TValue](TValue value, JsonSerializerOptions options)
   at Program.<Main>$(String[] args) in C:\GitHubRepos\DotNetTextJsonSerializerProblem\ConsoleApp1\Program.cs:line 12The program '[42624] ConsoleApp1.exe: Program Trace' has exited with code 0 (0x0).

Regression?

I have identified the issue in both .Net 6 and .Net 7 Preview 2. I have not tested other versions.

Known Workarounds

No response

Configuration

No response

Other information

No response

EDIT @krwq: fixed code formatting and call stack

@dotnet-issue-labeler dotnet-issue-labeler bot added area-System.Text.Json untriaged New issue has not been triaged by the area owner labels Mar 20, 2022
@ghost
Copy link

ghost commented Mar 20, 2022

Tagging subscribers to this area: @dotnet/area-system-text-json
See info in area-owners.md if you want to be subscribed.

Issue Details

Description

With System.Text.Json when trying to serialize a class that is inheriting from a class and is using the new keyword for a property and the new property and the hidden property return different types that has the same name (e.g. "Class1") and both properties are set to [JsonIgnore] an exception is thrown with the following message:

An item with the same key has already been added. Key: class1

It looks like there are actual two problems:

First that two types cannot have the same name apparently.

Second that it only looks at both types when both properties are set to [JsonIgnore]. All other combinations seems to work.

I have identified the issue in both .Net 6 and .Net 7 Preview 2.

Reproduction Steps

Run following code as a Console app in .Net 6 or 7:

`using System.Text.Json.Serialization;

Console.WriteLine("Hello, World!");

MyNamespace.Class2 class2 = new MyNamespace.Class2();

string jsonText;

try
{
jsonText = System.Text.Json.JsonSerializer.Serialize(class2);
}
catch (Exception ex)
{
jsonText = "EXCEPTION: " + ex.Message;
}

Console.WriteLine(jsonText);

namespace MyNamespace
{
public class Class1
{

}

public class Class2 : MyNamespaceBase.Class2
{
    [JsonIgnore]
    public new Class1 class1 => new Class1();
}

}

namespace MyNamespaceBase
{
public class Class1
{

}

public class Class2
{
    [JsonIgnore]
    public Class1 class1 => new Class1();
}

}`

Expected behavior

Should not throw exception. Should serialize the object.

Actual behavior

Following exception is thrown:

System.ArgumentException: An item with the same key has already been added. Key: class1
at System.Collections.Generic.Dictionary2.TryInsert(TKey key, TValue value, InsertionBehavior behavior) at System.Collections.Generic.Dictionary2.Add(TKey key, TValue value)
at System.Text.Json.Serialization.Metadata.JsonTypeInfo.CacheMember(Type declaringType, Type memberType, MemberInfo memberInfo, Boolean isVirtual, Nullable1 typeNumberHandling, Boolean& propertyOrderSpecified, Dictionary2& ignoredMembers)
at System.Text.Json.Serialization.Metadata.JsonTypeInfo..ctor(Type type, JsonConverter converter, Type runtimeType, JsonSerializerOptions options)
at System.Text.Json.JsonSerializerOptions.g__CreateJsonTypeInfo|120_0(Type type, JsonSerializerOptions options)
at System.Collections.Concurrent.ConcurrentDictionary2.GetOrAdd(TKey key, Func2 valueFactory)
at System.Text.Json.JsonSerializer.GetTypeInfo(JsonSerializerOptions options, Type runtimeType)
at System.Text.Json.JsonSerializer.Serialize[TValue](TValue value, JsonSerializerOptions options)
at Program.

$(String[] args) in C:\GitHubRepos\DotNetTextJsonSerializerProblem\ConsoleApp1\Program.cs:line 12The program '[42624] ConsoleApp1.exe: Program Trace' has exited with code 0 (0x0).

Regression?

I have identified the issue in both .Net 6 and .Net 7 Preview 2. I have not tested other versions.

Known Workarounds

No response

Configuration

No response

Other information

No response

Author: AndersWangRask
Assignees: -
Labels:

area-System.Text.Json, untriaged

Milestone: -

@krwq krwq added this to the 7.0.0 milestone Mar 24, 2022
@krwq krwq added bug and removed untriaged New issue has not been triaged by the area owner labels Mar 24, 2022
@krwq
Copy link
Member

krwq commented Mar 24, 2022

I'm putting it in 7.0.0 milestone for now so it doesn't disappear from our radar. I do not promise it will be fixed in this timeline though. We have a set of issues related to JsonIgnore and this is another one.

@krwq krwq changed the title System.Text.Json exception when serializing an inheriting type where a new property returns a new type with same name Serializing type which hides inherited property with both properties ignored throws ArgumentException Mar 24, 2022
@eiriktsarpalis eiriktsarpalis modified the milestones: 7.0.0, 8.0.0 Aug 1, 2022
@eiriktsarpalis eiriktsarpalis modified the milestones: 8.0.0, Future Sep 28, 2022
@eiriktsarpalis eiriktsarpalis modified the milestones: Future, 8.0.0 Jun 6, 2023
@eiriktsarpalis eiriktsarpalis linked a pull request Jun 6, 2023 that will close this issue
@ghost ghost locked as resolved and limited conversation to collaborators Jul 16, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants