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

如何用Newtonsoft.Json实现C#对象的双规则序列化适配多客户端

针对内外客户端实现不同的Newtonsoft.Json序列化/反序列化规则

针对内部、外部客户端需要不同JSON字段名的需求,用Newtonsoft.Json可以通过两种常用方案实现,同时保留双向序列化能力:

方案一:自定义契约解析器(不修改原类)

如果不能修改现有C#类的代码,或者需要批量管理属性名映射,推荐用这种方式。核心是创建自定义ContractResolver,在序列化时动态替换指定属性名。

实现步骤

  1. 定义原类:
public class MyClass
{
    public string Customer { get; set; }
}
  1. 编写外部客户端专用的契约解析器:
public class ExternalContractResolver : DefaultContractResolver
{
    // 维护类-属性名映射表,按需扩展
    private readonly Dictionary<Type, Dictionary<string, string>> _propertyMappings = new()
    {
        { 
            typeof(MyClass), 
            new Dictionary<string, string> { { nameof(MyClass.Customer), "Mandant" } }
        }
    };

    protected override string ResolvePropertyName(string propertyName)
    {
        // 检查当前处理的类型是否有属性映射,有则返回外部字段名,否则用原属性名
        if (_propertyMappings.TryGetValue(CurrentType, out var mappings) && mappings.TryGetValue(propertyName, out var newName))
        {
            return newName;
        }
        return base.ResolvePropertyName(propertyName);
    }
}
  1. 序列化/反序列化调用:
var myObj = new MyClass { Customer = "MyCustomer" };

// 内部客户端:用默认配置,直接输出原属性名
var internalSettings = new JsonSerializerSettings();
string internalJson = JsonConvert.SerializeObject(myObj, Formatting.Indented, internalSettings);
// 输出:
// {
//   "Customer": "MyCustomer"
// }

// 外部客户端:使用自定义契约解析器替换字段名
var externalSettings = new JsonSerializerSettings
{
    ContractResolver = new ExternalContractResolver()
};
string externalJson = JsonConvert.SerializeObject(myObj, Formatting.Indented, externalSettings);
// 输出:
// {
//   "Mandant": "MyCustomer"
// }

// 反序列化示例
string internalInput = "{\"Customer\": \"NewCustomer\"}";
MyClass internalResult = JsonConvert.DeserializeObject<MyClass>(internalInput, internalSettings);

string externalInput = "{\"Mandant\": \"NewCustomer\"}";
MyClass externalResult = JsonConvert.DeserializeObject<MyClass>(externalInput, externalSettings);

方案二:JsonProperty标记+内部专用解析器(修改原类)

如果允许修改C#类的代码,这种方式更简洁。给属性标记外部用的字段名,然后用内部解析器强制使用原属性名。

实现步骤

  1. 给类属性标记外部字段名:
public class MyClass
{
    [JsonProperty("Mandant")]
    public string Customer { get; set; }
}
  1. 编写内部客户端专用的契约解析器:
public class InternalContractResolver : DefaultContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        var property = base.CreateProperty(member, memberSerialization);
        // 忽略JsonProperty指定的名称,强制使用属性本身的名称
        property.PropertyName = member.Name;
        return property;
    }
}
  1. 序列化/反序列化调用:
var myObj = new MyClass { Customer = "MyCustomer" };

// 内部客户端:用自定义解析器输出原属性名
var internalSettings = new JsonSerializerSettings
{
    ContractResolver = new InternalContractResolver()
};
string internalJson = JsonConvert.SerializeObject(myObj, Formatting.Indented, internalSettings);
// 输出:{"Customer": "MyCustomer"}

// 外部客户端:直接用默认配置,输出JsonProperty标记的名称
var externalSettings = new JsonSerializerSettings();
string externalJson = JsonConvert.SerializeObject(myObj, Formatting.Indented, externalSettings);
// 输出:{"Mandant": "MyCustomer"}

// 反序列化同样适用
string internalInput = "{\"Customer\": \"NewCustomer\"}";
MyClass internalResult = JsonConvert.DeserializeObject<MyClass>(internalInput, internalSettings);

string externalInput = "{\"Mandant\": \"NewCustomer\"}";
MyClass externalResult = JsonConvert.DeserializeObject<MyClass>(externalInput, externalSettings);

方案选择

  • 若原类不可修改,或需统一管理大量属性映射,选方案一
  • 若原类可修改,且仅少数属性需要重命名,选方案二,代码更简洁

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 11:52:24