You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

迁移旧API到.NET Core时System.Text.Json序列化重名属性碰撞报错如何解决

问题根因

  1. 你配置的PropertyNameCaseInsensitive = true仅作用于反序列化阶段,用来实现忽略大小写匹配C#类属性,对序列化逻辑没有任何影响,无法解决你要输出大小写不同同名属性的需求。
  2. 报错的核心原因:
    • 默认System.Text.Json序列化时如果开启了全局驼峰命名转换,你匿名类中定义的id和ID两个属性会被统一转换为id,触发属性名重复校验。
    • 匿名类无法自定义序列化后的属性名,无法规避命名策略的转换规则。

解决方案

方案1:使用字典构造返回数据(改造成本最低)

直接在查询投影中返回Dictionary<string, object>类型,手动指定JSON属性名,不会受全局命名策略影响,代码示例如下:

[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 Dictionary<string, object>
        {
            ["Id"] = o.Id,
            ["id"] = o.Id
        }).ToListAsync();
    return contacts;
}

你不需要修改现有的Json全局配置,就能得到预期的输出结构。

方案2:自定义DTO类 + 显式指定序列化属性名

如果你需要强类型约束,可以自定义DTO类,通过JsonPropertyName特性显式指定序列化后的属性名:
首先定义DTO类:

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

    [JsonPropertyName("id")]
    public int LowerCaseId { get; set; }
}

修改Action中的投影逻辑:

[HttpGet]
public async Task<ActionResult<IEnumerable<ContactDto>>> 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 ContactDto
        {
            Id = o.Id,
            LowerCaseId = o.Id
        }).ToListAsync();
    return contacts;
}

需要注意如果你的全局Json配置中开启了驼峰命名转换,JsonPropertyName指定的属性名优先级高于全局配置,不会被覆盖。


内容的提问来源于stack exchange,提问作者Plarent Haxhidauti

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 03:27:01