首页 > 解决方案 > 如何序列化具有相同复杂道具类型但名称不同的对象

问题描述

我有下一个模型

public class Record
{
    public User User{ get; set; }

    public User Sister { get; set; }

    public User Mother { get; set; }

    ...
}

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

    public string Id { get; set; }
}

序列化后的目标 json 应如下所示

{
   "user":{
      "user_name":"UserName",
      "user_id":"id"
   },
   "sister":{
      "sister1_name":"UserName",
      "sister1_id":"id"
   },
   "mother":{
      "mother_name":"UserName",
      "mother_id":"id"
   }
}

问题是所有这些字段都具有相同的类型,但我需要为每个属性提供不同的名称。所以在这里使用属性不是一个选项。我试着玩CustomContractResolver,但没有走得太远。有可能在属性名称上设置名称解析器会很好,但据我所知这是不可能的。我们有另一种方法可以做到干净和可扩展吗?PS我正在使用Newtonsoft Json,但如果有的话我会考虑其他选项

标签: c#json

解决方案


另一种方法是这样的:

我们可以使您的客户类抽象并为每种类型的客户(用户/姐妹/母亲)创建一个类

public class Record
{
    public User User { get; set; }

    public Sister Sister { get; set; }

    public Mother Mother { get; set; }
}

public abstract class Customer
{
    public string Name { get; set; }
    public string Id { get; set; }
}

[JsonPrefix(Prefix = "User")]
public class User : Customer { }
[JsonPrefix(Prefix = "Sister1")]
public class Sister : Customer { }
[JsonPrefix(Prefix = "Mother")]
public class Mother : Customer { }

现在我们为它创建 JsonPrefix 属性和自定义序列化程序,因此生成的 json 具有前缀。

public class JsonPrefix : Attribute
{
    public string Prefix { get; set; }
}

public class CustomResolver : DefaultContractResolver
{

    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        var ret = new List<JsonProperty>();
        foreach (var prop in base.CreateProperties(type, memberSerialization))
        {
            var cst = type.GetCustomAttribute<JsonPrefix>();
            if (cst != null)
                prop.PropertyName = $"{cst.Prefix}_{prop.PropertyName}";

            ret.Add(prop);
        }
        return ret;
    }
}

最后你这样称呼:

        var data1 = new Record();
        data1.User = new User() { Name = "Test" };
        data1.Sister = new Sister() { Name = "Test2" };
        data1.Mother = new Mother() { Name = "Test3" };

        JsonSerializerSettings settings = new JsonSerializerSettings
        {
            ContractResolver = new CustomResolver(),
            Formatting = Formatting.Indented
        };

        string json = JsonConvert.SerializeObject(data1, settings);

生成的 Json 就像您需要它一样。唯一的缺点是需要为json中的新数据类型创建一个从客户类继承的新类。


推荐阅读