ASP.NET Core Web API中ExpandoObject构建多语言JSON出现键值互换问题
问题根因
- 方法参数传反:确认你调用的
TryAdd方法参数顺序没有颠倒,ExpandoObject的TryAdd扩展方法第一个参数为键,第二个为值,传反会直接导致键值互换。 - 数据源字段映射错误:检查数据库查询逻辑是否存在字段映射颠倒,实际获取到的
countryData.Name是数值70、countryData.Value是阿拉伯语国家名,和你预期的字段赋值完全相反。 - 序列化配置异常:ASP.NET Core 默认使用 System.Text.Json 序列化
ExpandoObject时,会将其识别为IDictionary<string, object>类型处理。如果你全局配置了以下任意一种序列化规则,会导致键值反转:- 引入了针对字典的自定义转换器,逻辑中存在键值反转的错误
- 配置了错误的
DictionaryKeyPolicy,或是引入了处理多语言字符的自定义逻辑,遇到阿拉伯语等非ASCII字符作为键时触发异常,fallback 为将数值作为键、字符串作为值返回
- 中间件/过滤器篡改返回值:如果你项目中注册了全局响应格式化过滤器、自定义中间件,存在遍历字典类型返回值并做键值转换的逻辑,也可能意外把
ExpandoObject的键值对反转。
解决方案
- 先做本地校验:在
return result之前打断点,将country转为IDictionary<string, object>类型查看键值对是否符合预期,先排除赋值逻辑错误的问题。 - 检查序列化配置:
- 使用 System.Text.Json 的场景下,检查
Program.cs中AddJsonOptions的配置,移除针对字典的自定义转换器,测试关闭DictionaryKeyPolicy后的返回结果。 - 使用 Newtonsoft.Json 的场景下,检查
AddNewtonsoftJson的配置,确认没有自定义的字典序列化规则。
- 使用 System.Text.Json 的场景下,检查
- 规避动态键序列化风险:如果确认是非ASCII字符作为动态键导致的序列化异常,可以把返回结构调整为固定键的对象,避免动态键的兼容问题,示例如下:
public class CountryItem { public string CountryName { get; set; } public int Value { get; set; } } public List<CountryItem> PrepareDynamicResult() { var result = new List<CountryItem>(); // 该数据从数据库获取 var countryData = new { Name= "<country-name-in-arabic>", Value= 70 }; result.Add(new CountryItem { CountryName = countryData.Name, Value = countryData.Value }); return result; }
内容的提问来源于stack exchange,提问作者amol
相关产品推荐
相关产品推荐

