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

如何在单个对象而非列表上使用Newtonsoft Json的ItemTypeNameHandling

解决方案

要让Newtonsoft.Json为单个非集合属性(如CommandTest)添加类型信息,和集合元素的处理方式一致,有以下几种直接可行的方法:

1. 为目标属性单独指定TypeNameHandling

最直接的方式是在目标属性上通过[JsonProperty]特性显式设置TypeNameHandling值,强制序列化时输出类型信息:

using Newtonsoft.Json;

public interface ICommand { }
public class CommandA : ICommand { }

public class TestDto
{
    // 集合默认在TypeNameHandling.Auto下会自动加类型信息
    public List<ICommand> Commands { get; set; }

    // 为单个属性强制开启类型信息输出
    [JsonProperty(TypeNameHandling = TypeNameHandling.Objects)]
    public ICommand CommandTest { get; set; }
}

效果

序列化后,CommandTest属性会像集合中的元素一样,携带$type字段,示例输出片段:

{
"Commands": [
{"$type": "CommandA, YourAssembly", ...}
],
"CommandTest": {"$type": "CommandA, YourAssembly", ...}
}

2. 全局配置结合属性覆盖(可选)

如果全局已经设置了TypeNameHandling.Auto,但需要针对单个非多态属性强制加类型信息,同样可以用上述特性覆盖全局配置。

注意事项

  • 推荐使用TypeNameHandling.Objects只给引用类型对象添加类型信息,避免TypeNameHandling.All给所有类型(包括值类型)冗余添加$type。
  • 反序列化时需注意类型注入风险,建议配合SerializationBinder限制允许反序列化的类型,避免安全问题:
    var settings = new JsonSerializerSettings
    {
        TypeNameHandling = TypeNameHandling.Auto,
        SerializationBinder = new SafeTypeBinder()
    };
    
    public class SafeTypeBinder : SerializationBinder
    {
        public override Type BindToType(string assemblyName, string typeName)
        {
            // 只允许指定类型的反序列化
            if (typeName == "CommandA, YourAssembly")
                return typeof(CommandA);
            throw new JsonSerializationException($"不允许的类型: {typeName}");
        }
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 02:25:03