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

Pla*_*uti 8 c# json.net asp.net-core

我正在将旧 API 迁移到 .net core Web api,并且其中一个响应两次包含相同的值,因此我使用 .NET 5 的本机 Json 库,并且尝试在JSON 响应,“Id”和“id”

{
...

"Id": "10",

"id": "10"

...
}
Run Code Online (Sandbox Code Playgroud)

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

services.AddControllers().AddJsonOptions(options =>
    { options.JsonSerializerOptions.PropertyNameCaseInsensitive = true; });
Run Code Online (Sandbox Code Playgroud)

我的行动方法

[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;
}
Run Code Online (Sandbox Code Playgroud)

序列化时,我收到“与另一个属性发生冲突的 JSON 属性名称”。我想我错过了一些东西,而且我陷入了困境。

sto*_*ran 9

根据文档PropertyNameCaseInsensitive:​

获取或设置一个值,该值确定属性名称在反序列化期间是否使用不区分大小写的比较。

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

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

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

所以解决办法就是设置PropertyNameCaseInsensitivefalse并使用PropertyNamingPolicy = JsonNamingPolicy.CamelCase(为默认值,下面省略):

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

    public string SomeString { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

启动:

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

这应该给出:

{
    "Id": 2,
    "id": 3,
    "someString": "..."
}
Run Code Online (Sandbox Code Playgroud)