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