ExpandoObject反序列化动态JSON时,访问不存在属性抛异常的解决方法
动态JSON属性访问时返回null而非抛出异常的解决方案
方案1:自定义安全包装类适配ExpandoObject
ExpandoObject是密封类,无法直接修改其行为,但可以通过包装类实现安全访问逻辑。自定义一个继承DynamicObject的类,内部持有ExpandoObject,重写属性获取方法,当属性不存在时返回null,同时支持嵌套属性的链式安全访问。
public class NullSafeExpando : DynamicObject { private readonly ExpandoObject _expando; private readonly IDictionary<string, object> _expandoDict; public NullSafeExpando(ExpandoObject expando) { _expando = expando; _expandoDict = _expando as IDictionary<string, object>; } public override bool TryGetMember(GetMemberBinder binder, out object result) { if (_expandoDict.TryGetValue(binder.Name, out var value)) { // 嵌套的ExpandoObject也包装成安全实例,支持链式访问 result = value is ExpandoObject nested ? new NullSafeExpando(nested) : value; return true; } // 属性不存在时返回null result = null; return true; } // 可选:支持属性赋值 public override bool TrySetMember(SetMemberBinder binder, object value) { _expandoDict[binder.Name] = value is NullSafeExpando safeValue ? safeValue._expando : value; return true; } }
使用方式:
var rawExpando = JsonConvert.DeserializeObject<ExpandoObject>(jsonScript, new ExpandoObjectConverter()); dynamic jsonMeta = new NullSafeExpando(rawExpando); // 安全访问不存在的属性返回null,空条件运算符正常生效 string plotText = jsonMeta.plot?.name?.text;
方案2:使用Newtonsoft.Json内置的JObject(推荐)
JObject是Newtonsoft.Json专门为动态JSON设计的类型,天生支持访问不存在的属性时返回null,无需额外封装,代码更简洁。
dynamic jsonMeta = JObject.Parse(jsonScript); // 直接安全访问,空条件链式调用完全正常 string plotText = jsonMeta.plot?.name?.text;
这个方案无需自定义类,性能和易用性都更优,是动态JSON场景下的首选方案。
方案3:自定义动态元对象(不推荐)
通过实现DynamicMetaObjectProvider来修改动态绑定逻辑,但实现复杂度高,维护成本大,除非有特殊需求,否则不建议使用。
方案对比
- 自定义NullSafeExpando:保留ExpandoObject的原有特性,适合已经基于ExpandoObject开发的场景。
- JObject:原生支持安全访问,代码更简洁,性能更优,优先推荐。
内容的提问来源于stack exchange,提问作者rboy
相关产品推荐
相关产品推荐

