『 再看.NET7』让json序列化体现多态

Posted dotNET跨平台

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了『 再看.NET7』让json序列化体现多态相关的知识,希望对你有一定的参考价值。

从System.Text.Json诞生,就在努力增加功能和提升性能,在.NET7中,又带来了多态的适配。

下面是一个父类Customer,两个子类,WechatCustomer和LineCustomer。

public class Customer

    public string Name  get; set; 
    public string Address  get; set; 
    public string City  get; set; 
    public string Region  get; set; 
    public string PostalCode  get; set; 
    public string EMail  get; set; 
    public string Tel  get; set; 



public class WechatCustomer : Customer

    public string? WechatNo  get; set; 

public class LineCustomer : Customer

    public string? LineNo  get; set; 

分别用一个打印方法PrintCustomer输出两个子类对象。

var wechatCustomer = new WechatCustomer

    Name = "张三",
    City = "东京",
    Region = "中央区",
    Address = "1-56-326",
    PostalCode = "3000235",
    EMail = "abcde@gmail.com",
    Tel = "08-9563-2356",
    WechatNo = "wechat_gsw" 
;
var lineCustomer = new LineCustomer

    Name = "张三",
    City = "东京",
    Region = "中央区",
    Address = "1-56-326",
    PostalCode = "3000235",
    EMail = "abcde@gmail.com",
    Tel = "08-9563-2356",
    LineNo = "line_gsw"
;
//共用打印方法
void PrintCustomer(Customer customer)

    var options = new JsonSerializerOptions
    
        Encoder = javascriptEncoder.UnsafeRelaxedJsonEscaping,
        WriteIndented = true
    ;
    var json = JsonSerializer.Serialize<Customer>(customer, options);
    Console.WriteLine(json);



PrintCustomer(wechatCustomer);
PrintCustomer(lineCustomer);

输出结果是:


  "Name": "张三",
  "Address": "1-56-326",
  "City": "东京",
  "Region": "中央区",
  "PostalCode": "3000235",
  "EMail": "abcde@gmail.com",
  "Tel": "08-9563-2356"


  "Name": "张三",
  "Address": "1-56-326",
  "City": "东京",
  "Region": "中央区",
  "PostalCode": "3000235",
  "EMail": "abcde@gmail.com",
  "Tel": "08-9563-2356"

现在丢失了子类的属性WechatNo和LineNo,在.NET7中,可以通过两种方式来保证不丢失这种多态产生的新的属性:特性和自定义类型信息解析器。

特性:

[JsonPolymorphic(TypeDiscriminatorPropertyName = "CustomerType")]
[JsonDerivedType(typeof(WechatCustomer), typeDiscriminator: "wechatCustomer")]
[JsonDerivedType(typeof(LineCustomer), typeDiscriminator: "lineCustomer")]
public class Customer

……

通过给父类Customer添加特性,来达到json化的效果。再次输出如下:


  "CustomerType": "wechatCustomer",
  "WechatNo": "wechat_gsw",
  "Name": "张三",
  "Address": "1-56-326",
  "City": "东京",
  "Region": "中央区",
  "PostalCode": "3000235",
  "EMail": "abcde@gmail.com",
  "Tel": "08-9563-2356"


  "CustomerType": "lineCustomer",
  "LineNo": "line_gsw",
  "Name": "张三",
  "Address": "1-56-326",
  "City": "东京",
  "Region": "中央区",
  "PostalCode": "3000235",
  "EMail": "abcde@gmail.com",
  "Tel": "08-9563-2356"

可以看到,JsonPolymorphic特性是定义一个标注子类名称的属性customerType,而JsonDerivedType是定义两个子类的特性。

自定义类型信息解析器:

首先定义自定义类型信息解析器class,可以看出,他的作用与上面的特性是一样的。

public class PolymorphicTypeResolver : DefaultJsonTypeInfoResolver

    public override JsonTypeInfo GetTypeInfo(Type type, JsonSerializerOptions options)
    
        JsonTypeInfo jsonTypeInfo = base.GetTypeInfo(type, options);


        Type basePointType = typeof(Customer);
        if (jsonTypeInfo.Type == basePointType)
        
            jsonTypeInfo.PolymorphismOptions = new JsonPolymorphismOptions
            
                TypeDiscriminatorPropertyName = "CustomerType",
                DerivedTypes =
                
                    new JsonDerivedType(typeof(WechatCustomer), "wechatCustomer"),
                    new JsonDerivedType(typeof(LineCustomer), "lineCustomer")
                
            ;
        
        return jsonTypeInfo;
    

这个时候,Customer上的特性就可以没有了,只要在PrintCustomer方法中给options加个属性即可。

void PrintCustomer(Customer customer)

    var options = new JsonSerializerOptions
    
        TypeInfoResolver = new PolymorphicTypeResolver(),
        Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
        WriteIndented = true
    ;
    var json = JsonSerializer.Serialize<Customer>(customer, options);
    Console.WriteLine(json);

输出结果与特性方式是一样的。这里不再赘述。

上面两种方式,也可以把对应的json字符串反序列化回来。

以上是关于『 再看.NET7』让json序列化体现多态的主要内容,如果未能解决你的问题,请参考以下文章

『 再看.NET7』泛性特性使用场景

『 再看.NET7』string的进化

『 再看.NET7』是否数值类型

『 再看.NET7』看看required属性有什么不同

『 再看.NET7』新的访问修饰符——file

第八天(下) 多态