构造可反序列化后通过索引访问动态对象属性的字符串报错,如何解决?
问题原因分析
- System.Text.Json的dynamic本质是JsonElement:
JsonSerializer.Deserialize<dynamic>返回的实际类型是JsonElement,它不像Newtonsoft.Json的JObject那样原生支持字符串索引访问属性。 - 索引器重载不匹配:
- 若传入的JSON是数组格式,
jsonData会被解析为代表数组的JsonElement,其索引器仅支持整数下标(用于访问数组元素),用字符串"myvalue1"索引必然触发重载匹配错误。 - 即使传入的是JSON对象,
JsonElement本身也没有字符串类型的索引器,正确访问属性需调用GetProperty("myvalue1"),但客户代码使用了[]字符串索引的写法,运行时绑定器找不到对应方法,同样会报错。
- 若传入的JSON是数组格式,
修改MyMethod的可行方案
方案一:传入正确的JSON对象格式
如果之前构造的是数组类型的JSON,改为构造标准的键值对对象JSON,确保客户代码能解析到对象类型的JsonElement:
public void MyMethod() { // 构造包含目标属性的JSON对象字符串 string validJson = "{\"myvalue1\":\"your_value1\",\"myvalue2\":\"your_value2\"}"; CustomerMethod(validJson); }
方案二:适配System.Text.Json的动态访问逻辑
由于客户代码无法修改,可在MyMethod中先将数据序列化为ExpandoObject,再通过自定义配置序列化,让客户代码的反序列化能得到支持字符串索引的动态对象:
using System.Dynamic; using System.Text.Json; using System.Text.Json.Serialization; public void MyMethod() { dynamic data = new ExpandoObject(); data.myvalue1 = "your_value1"; data.myvalue2 = "your_value2"; // 使用ExpandoObject转换器序列化,确保反序列化后能被字符串索引访问 var options = new JsonSerializerOptions { Converters = { new ExpandoObjectConverter() } }; string jsonContent = JsonSerializer.Serialize(data, options); CustomerMethod(jsonContent); }
注:此方案利用
ExpandoObject的动态特性,运行时会自动适配字符串索引器,避免绑定错误。
替代方案:改用Newtonsoft.Json序列化
如果项目允许引入Newtonsoft.Json库,可在MyMethod中用它来构造JSON,因为Newtonsoft.Json的Deserialize<dynamic>返回的JObject原生支持字符串索引,完全适配客户代码的写法:
using Newtonsoft.Json; public void MyMethod() { dynamic data = new ExpandoObject(); data.myvalue1 = "your_value1"; data.myvalue2 = "your_value2"; string jsonContent = JsonConvert.SerializeObject(data); CustomerMethod(jsonContent); }
内容的提问来源于stack exchange,提问作者Bluemarble
相关产品推荐
相关产品推荐

