.net 使用Newtonsoft.Json使用两个不同的JsonConverter序列化C#对象

whhtz7ly  于 2023-06-25  发布在  .NET
关注(0)|答案(3)|浏览(154)

我的用例要求我为多个客户端(基本上是内部客户端和外部客户端)序列化/反序列化C#对象。我的内部客户端只是使用objects属性作为JSON数据的命名方案。我的外部客户端具有完全相同的属性,但希望为某些属性使用不同的名称。在这个szenario中,我的客户希望将下面的Customer字段重命名为Mandant。然而,对于我来说,仍然能够序列化为Customer作为字段名是至关重要的。只有在某些情况下,我需要能够为我的外部客户端序列化。我目前正在使用Newtonsoft.Json
我的C#类可以看起来像这样:

public class MyClass
{
    public string Customer {get; set;}
}

我的期望是我可以用两种不同的方式序列化/反序列化,例如:我的外部客户想要字段Customer被重命名为Mandant.
为内部客户端序列化:

{
   "Customer": "MyCustomer"
}

为外部客户端序列化:

{
   "Mandant": "MyCustomer"
}
llycmphe

llycmphe1#

请区分您的内部业务逻辑DTO(或POCO)和您发布到外部系统的数据(无论是客户还是您自己的其他程序/工具/库)。
假设你有某种数据源(例如Sql DB、Cosmos DB、Redis缓存等)。所使用的源代码通常有一些关于必须如何设计类的约定(Sql大多具有Id属性或遵循某种模式来处理1:多关系; Cosmos需要分区密钥; Redis需要一些缓存键;你应该坚持这些数据源规则,并对你的对象建模,以最好地适应给定的源规则和你的需求(例如,读优化、写优化等)。
在下一步中,定义DTO如何呈现给其他系统。根据客户的要求向他们提供属性和结构(这也可能是您,但用于相同或其他解决方案中的其他项目)。然后编写一个转换器/Map器,它接受一个类型A的对象并产生一个类型B的对象(为此,你可以看看 AutoMapper 来简化这个过程)。同样,为相同的目标类型创建不同的DTO也是有意义的,但不同的操作(例如创建/更新)。
所有这些步骤都需要一些努力,但从长远来看,区分不同的操作和/或客户会容易得多,并防止您创建试图处理多个事情的god类(例如:客户)一次。

klr1opcd

klr1opcd2#

您可以使用自定义ContractResolver

List<string[]> customerReplaces = new List<string[]> { 
                    new string[] { "Customer", "Mandant" } 
                   };

    var json = JsonConvert.SerializeObject(customer,
                Newtonsoft.Json.Formatting.Indented,
                new JsonSerializerSettings
                {
                    ContractResolver = new ReplaceNamesContractResolver(customerReplaces)
                });

public class ReplaceNamesContractResolver : DefaultContractResolver
{
    private readonly List<string[]> _replaces;

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {

        JsonProperty property = base.CreateProperty(member, memberSerialization);

        var newName = _replaces.Where(v => v[0] == property.PropertyName)
                               .FirstOrDefault()?[1];

        if (newName != null) property.PropertyName = newName;

        return property;
    }

    public ReplaceNamesContractResolver(List<string[]> replaces)
    {
        _replaces = replaces;
    }
}
yjghlzjz

yjghlzjz3#

使用Newtonsoft.Json中的JsonProperty属性:

using Newtonsoft.Json;

public class MyClass 
{ 
    [JsonProperty("Customer")]
    public string Customer { get; set; }

    [JsonProperty("Mandant")]
    public string Mandant 
    { 
        get { return Customer; } 
        set { Customer = value; } 
    }
}

然后这样使用:

var obj = new MyClass { Customer = "MyCustomer" };

var SerializedForInternalClient = JsonConvert.SerializeObject(obj); // Output: {"Customer":"MyCustomer"}
var SerializedForExternalClient = JsonConvert.SerializeObject(obj); // Output: {"mandant":"MyCustomer"}

var DeserializedForInternalClient = JsonConvert.DeserializeObject<MyClass>(SerializedForInternalClient); // Output: "MyCustomer"
var DeserializedForExternalClient = JsonConvert.DeserializeObject<MyClass>(SerializedForExternalClient); // Output: "MyCustomer"

相关问题