Home > database >  .NET Core - The JSON property name for collides with another property
.NET Core - The JSON property name for collides with another property

Time:10-08

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.

CodePudding user response:

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": "..."
}
  • Related