.NET Core - JSON 属性 名称与另一个 属性 冲突

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

我正在将旧的 API 迁移到 .net 核心网络 api,并且其中一个响应两次包含相同的值,所以我正在使用本机 Json 库.NET 5,我试图在 JSON 响应中两次获得相同的值,'Id' 和 'id'

{
...

"Id": "10",

"id": "10"

...
}

在我的 Startup ConfigurationServices 中,我配置了 Json 选项,如下所示:

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

我的操作方法

[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;
}

在序列化时,我收到“JSON 属性 名称与另一个 属性 冲突。” 我想我错过了什么,我被困在了这里。

根据 docs PropertyNameCaseInsensitive:

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

所以这个标志与序列化和 API 输出格式无关。在示例代码中,它被设置为 true。因此,在反序列化过程中,JSON 属性 名称应该以不区分大小写的方式与目标 class 的单个 属性 匹配。但是,存在冲突 - 有两个候选属性 - Idid。所以没有意义。

在内部,它作为 属性 查找的不区分大小写的字典实现(由 Rider 反编译 .Net 5):

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

所以解决方法是将PropertyNameCaseInsensitive设置为false并使用PropertyNamingPolicy = JsonNamingPolicy.CamelCase(这是默认值,下面省略):

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

    public string SomeString { get; set; }
}

启动:

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

这应该给出:

{
    "Id": 2,
    "id": 3,
    "someString": "..."
}