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

含IEnumerable属性的类序列化时,内部对象属性未遵循命名策略

问题:包含IEnumerable属性的类序列化时,集合内对象属性未遵循命名策略

问题场景

当序列化包含非泛型IEnumerable属性的类时,集合内对象的属性没有应用已配置的驼峰命名策略,但直接序列化该集合时命名规则正常生效。

配置代码

services
  .AddOptions<MvcNewtonsoftJsonOptions>()
  .Configure<IHttpContextAccessor>((options, httpContextAccessor) => {
    options.UseCamelCasing(true);
  });

类定义

public class MyViewModel 
{ 
  public string Name { get; set; }
  // 非泛型IEnumerable属性
  public IEnumerable Items { get; set; }
}

public class MyListItem {
  public string Text { get; set; }
  public string Value { get; set; }
}

接口代码

public async Task<IActionResult> GetItems(TId id)
{
  var vm = new MyViewModel { 
    Name = "MyViewModel",
    Items = new List<MyListItem> { new MyListItem { Text = "A", Value = "1" }  }
  };

  return Json(vm);
}

当前序列化结果

{
  "name": "MyViewModel",
  "items": [{ "Text": "A", "Value": "1" }]
}

对比:直接序列化集合的结果

var jsonOptions = ViewContext.GetService<IOptions<MvcNewtonsoftJsonOptions>>();
var serializerSettings = jsonOptions.Value.SerializerSettings;
var vm = new MyViewModel { 
  Name = "MyViewModel",
  Items = new List<MyListItem> { new MyListItem { Text = "A", Value = "1" }  }
};

JsonConvert.SerializeObject(vm.Items, serializerSettings);

结果:

[{ "text": "A", "value": "1" }]

原因分析

核心问题在于MyViewModel中的Items是非泛型IEnumerable:

  • Newtonsoft.Json序列化非泛型集合时,无法推断集合内元素的具体类型,会将元素当作object处理。
  • 默认情况下,针对object类型的序列化不会自动应用配置的命名策略,因为无法提前知晓对象的属性结构。
  • 而直接序列化泛型List<MyListItem>时,框架明确知道元素类型,因此能正确应用驼峰命名规则。

解决方法

方法1:将属性改为泛型IEnumerable<MyListItem>

这是最直接且推荐的方案,修改MyViewModel的属性定义,让框架明确集合元素类型:

public class MyViewModel 
{ 
  public string Name { get; set; }
  // 替换为泛型版本
  public IEnumerable<MyListItem> Items { get; set; }
}

方法2:显式配置全局ContractResolver(无法修改属性类型时使用)

如果无法修改Items的类型,可以直接配置SerializerSettings的ContractResolver,确保所有类型(包括object类型的属性)都应用驼峰命名:

services.AddOptions<MvcNewtonsoftJsonOptions>()
        .Configure<IHttpContextAccessor>((options, httpContextAccessor) =>
        {
            // 显式设置驼峰命名解析器,替代UseCamelCasing(true)
            options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
        });

验证效果

修改后,序列化结果会符合预期:

{
  "name": "MyViewModel",
  "items": [{ "text": "A", "value": "1" }]
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 02:31:09