.NET Core - The JSON property name for collides with another property
Asked Answered
T

3

10

I'm migrating an old API to .net core web api and one of the responses includes the same value twice, so I'm using the native Json library of .NET 5 and I'm trying to get the same value twice in the JSON response, 'Id' and 'id'

{
...

"Id": "10",

"id": "10"

...
}

In my Startup, ConfigurationServices I configured the Json Option like this:

services.AddControllers().AddJsonOptions(options =>
    { options.JsonSerializerOptions.PropertyNameCaseInsensitive = true; });

My action method

[HttpGet]
public async Task<ActionResult<IEnumerable<object>>> GetContacts(string projectID)
{
    Project project = _context.Projects.Where(a => a.Name == projectID)
        .FirstOrDefault();
    var contacts = await _context.Contacts.Where(a => a.ProjectId == project.Id)
        .Select(o => new { id = o.Id, ID = o.Id}).ToListAsync();
    return contacts;
}

While serializing, I am getting the "The JSON property name for collides with another property." I think I'm missing something, and I'm stuck in this.

Trifling answered 5/10, 2021 at 10:6 Comment(2)
Any particular reason why do you need PropertyNameCaseInsensitive = true?Anglomania
@Anglomania I think this is to ignore the difference between Id and id, so I can return both. Please correct me if I'm wrongTrifling
A
13

According to docs for PropertyNameCaseInsensitive:

Gets or sets a value that determines whether a property's name uses a case-insensitive comparison during deserialization.

So this flag is not about serialization and API output formatting. In the example code it is set to true. Hence, during deserialization a JSON property name should be matched with a single property of a target class in a case-insensitive manner. However, there is a clash - there are two candidate properties - Id and id. So it does not make sense.

Internally it's implemented as a case-insensitive dictionary for property lookup (decompiled .Net 5 by Rider):

public JsonClassInfo(Type type, JsonSerializerOptions options)
{
    // ...
    Dictionary<string, JsonPropertyInfo> cache = new Dictionary<string, JsonPropertyInfo>(
        Options.PropertyNameCaseInsensitive
            ? StringComparer.OrdinalIgnoreCase
            : StringComparer.Ordinal);
    // ...
}

So the solution is to set PropertyNameCaseInsensitive to false and use PropertyNamingPolicy = JsonNamingPolicy.CamelCase (which is the default value and is omitted below):

public class SomeObject
{
    [JsonPropertyName("Id")]
    public int Id { get; set; }
   
    public int id { get; set; }

    public string SomeString { get; set; }
}

Startup:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers().AddJsonOptions(options => 
        options.JsonSerializerOptions.PropertyNameCaseInsensitive = false);
    // ...
}

This should give:

{
    "Id": 2,
    "id": 3,
    "someString": "..."
}
Anglomania answered 5/10, 2021 at 12:34 Comment(0)
M
0

I faced this issue while converting from JS to C# blazor through JSInterop.

In that case, the same property name on both the base and derived class also resulted in this error. Ensure the base class doesn't contain the same property name as the derived class.

Marcenemarcescent answered 6/10, 2023 at 5:5 Comment(0)
B
0

I had the same error, but in a different situation. My error was caused by the fact that the deserialized class implemented two interfaces who shared a (thus redundant) property. The C# compiler does not complain about this (does not even give a warning) and neither is there an error in the json. When one of the redundant properties, in one the interfaces, is removed, the error disappears.

Broughton answered 1/6 at 12:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.