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

继承DynamicObject的类调用JsonConvert.SerializeObject时动态属性未序列化

解决DynamicObject子类动态属性无法被JsonConvert序列化的问题

嘿,这个问题我之前帮不少开发者踩过坑——当你继承DynamicObject时,Json.NET默认确实不会自动序列化那些动态添加的属性,因为它没办法直接感知到这些属性的存在。别担心,咱们一步步来搞定它!

问题根源

DynamicObject只是提供了动态操作的框架(比如TrySetMember、TryGetMember方法),但它本身不会主动维护动态属性的集合,也不会主动把这些属性暴露给序列化工具。Json.NET默认只会反射类的静态定义的属性/字段,不会主动调用DynamicObject的方法去获取动态成员列表,所以自然就序列化不了那些动态添加的属性。

最直接的解决方案:重写GetDynamicMemberNames并维护属性存储

要让Json.NET识别动态属性,你需要做两件事:

  1. 在自定义类内部维护一个字典,用来存储所有动态添加的属性键值对
  2. 重写GetDynamicMemberNames方法,返回所有动态属性的名称列表

修改后的自定义类示例

public class MyDynamicClass : DynamicObject
{
    // 用来存储所有动态属性的键值对
    private readonly Dictionary<string, object> _dynamicProperties = new Dictionary<string, object>();

    // 重写TrySetMember,把动态属性存入字典
    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        _dynamicProperties[binder.Name] = value;
        return true; // 返回true表示设置成功
    }

    // 重写TryGetMember,从字典中获取动态属性值
    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        return _dynamicProperties.TryGetValue(binder.Name, out result);
    }

    // 关键:告诉Json.NET有哪些动态属性需要序列化
    public override IEnumerable<string> GetDynamicMemberNames()
    {
        return _dynamicProperties.Keys;
    }
}

测试序列化

// 创建动态对象并添加属性
dynamic myDynamicObj = new MyDynamicClass();
myDynamicObj.Username = "Usman";
myDynamicObj.Email = "usman@example.com";
myDynamicObj.Age = 28;

// 执行序列化
string jsonResult = JsonConvert.SerializeObject(myDynamicObj);

// 输出结果:{"Username":"Usman","Email":"usman@example.com","Age":28}
Console.WriteLine(jsonResult);

进阶方案:自定义ContractResolver(无需修改原类)

如果因为某些原因你不能修改原有的DynamicObject子类,可以通过自定义ContractResolver来强制Json.NET识别动态属性:

自定义ContractResolver代码

public class DynamicObjectContractResolver : DefaultContractResolver
{
    protected override JsonContract CreateContract(Type objectType)
    {
        // 针对所有继承自DynamicObject的类型创建动态契约
        if (typeof(DynamicObject).IsAssignableFrom(objectType))
        {
            var dynamicContract = new JsonDynamicContract(objectType);
            // 覆盖获取动态成员名称的逻辑
            dynamicContract.GetDynamicMemberNames = obj =>
            {
                if (obj is DynamicObject dynamicObj)
                {
                    return dynamicObj.GetDynamicMemberNames();
                }
                return Enumerable.Empty<string>();
            };
            return dynamicContract;
        }
        return base.CreateContract(objectType);
    }
}

使用方式

var serializerSettings = new JsonSerializerSettings
{
    ContractResolver = new DynamicObjectContractResolver()
};

string jsonResult = JsonConvert.SerializeObject(myDynamicObj, serializerSettings);

注意事项

  • 如果你没有在自定义类中维护动态属性的存储(比如用字典),即使重写了GetDynamicMemberNames也没用,因为Json.NET获取到属性名称后,还是需要通过TryGetMember拿到对应的值。
  • 如果动态属性包含复杂类型(比如自定义对象、枚举),Json.NET会自动处理,不需要额外配置,除非你有特殊的序列化需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:20:54