JsonSubTypes + Newtonsoft.Json 实现json 数据多态处理
在java 开发中jackson 的多太json 处理是一个很强大的功能,可以解决不少有意思的问题(比如动态方法执行,基于用户请求的json 数据,查找对应的消息处理器,不用单独进行判断处理),.net 也有一个扩展包JsonSubTypes 结合Newtonsoft.Json 可以实现类似jackson 的能力,以下是一个简单说明
基于JsonConverter模式的
此模式适合子类型确定的
- Animal
[JsonConverter(typeof(JsonSubtypes), "Sound")]
[JsonSubtypes.KnownSubType(typeof(Dog), "Bark")]
[JsonSubtypes.KnownSubType(typeof(Cat), "Meow")]
public class Animal
{
public virtual string Sound { get; }
public string Color { get; set; }
public virtual string DoMessage()
{
return $"The default says {Sound} and is a {Color}";
}
}
- Dog
public class Dog:Animal
{
public override string Sound { get; } = "Bark";
public string Breed { get; set; }
public override String DoMessage()
{
return $"The dog says {Sound} and is a {Breed}";
}
}
- Cat
public class Cat : Animal
{
public override string Sound { get; } = "Meow";
public bool Declawed { get; set; }
public override string DoMessage()
{
return $"The cat says {Sound} and is declawed: {Declawed}";
}
}
- 序列化集成
using jsonapp;
using Newtonsoft.Json;
var cat = new Cat()
{
Declawed= true,
Color = "Red"
};
var dog = new Dog()
{
Breed = "demoapp",
Color = "black"
};
var animalStrv1 = JsonConvert.SerializeObject(cat);
var animalStrv2 = JsonConvert.SerializeObject(dog);
Console.WriteLine(animalStrv1);
Console.WriteLine(animalStrv2);
var animalv1 = JsonConvert.DeserializeObject<Animal>(animalStrv1);
var animalv2 = JsonConvert.DeserializeObject<Animal>(animalStrv2);
Console.WriteLine(animalv1?.DoMessage());
Console.WriteLine(animalv2?.DoMessage());
- 效果
可以看到类方法可以正确的被调用,而不是Animal 的默认方法
{"Sound":"Meow","Declawed":true,"Color":"Red"}
{"Sound":"Bark","Breed":"demoapp","Color":"black"}
The cat says Meow and is declawed: True
The dog says Bark and is a demoapp
手工注册类型模式
此模式动态能力就比较强了
- Animal
去掉以前的属性标记
//
// [JsonConverter(typeof(JsonSubtypes), "Sound")]
// [JsonSubtypes.KnownSubType(typeof(Dog), "Bark")]
// [JsonSubtypes.KnownSubType(typeof(Cat), "Meow")]
public class Animal
{
public virtual string Sound { get; }
public string Color { get; set; }
public virtual string DoMessage()
{
return $"The default says {Sound} and is a {Color}";
}
}
- 注册类型
using jsonapp;
using JsonSubTypes;
using Newtonsoft.Json;
// 配置类型,此处我使用了字符串
var settings = new JsonSerializerSettings();
settings.Converters.Add(JsonSubtypesConverterBuilder
.Of(typeof(Animal), "Type") // type property is only defined here
.RegisterSubtype(typeof(Cat), "Cat")
.RegisterSubtype(typeof(Dog), "Dog")
.SerializeDiscriminatorProperty() // ask to serialize the type property
.Build());
var cat = new Cat()
{
Declawed= true,
Color = "Red"
};
var dog = new Dog()
{
Breed = "demoapp",
Color = "black"
};
// 序列化使用settings
var animalStrv1 = JsonConvert.SerializeObject(cat,settings);
var animalStrv2 = JsonConvert.SerializeObject(dog,settings);
Console.WriteLine(animalStrv1);
Console.WriteLine(animalStrv2);
// 反序列化也需要使用settings
var animalv1 = JsonConvert.DeserializeObject<Animal>(animalStrv1,settings);
var animalv2 = JsonConvert.DeserializeObject<Animal>(animalStrv2,settings);
Console.WriteLine(animalv1?.DoMessage());
Console.WriteLine(animalv2?.DoMessage());
- 效果
可以看到会自动多了一个type 字段
{"Type":"Cat","Sound":"Meow","Declawed":true,"Color":"Red"}
{"Type":"Dog","Sound":"Bark","Breed":"demoapp","Color":"black"}
The cat says Meow and is declawed: True
The dog says Bark and is a demoapp
说明
通过JsonSubTypes 对于.net 应该设计,就可以使用类似java jackson 模式了,是的一个很不错的包,可以方便的实现代码解耦
参考资料
https://github.com/manuc66/JsonSubTypes
https://github.com/JamesNK/Newtonsoft.Json
https://www.newtonsoft.com/json
https://manuc66.github.io/JsonSubTypes/
https://www.baeldung.com/java-jackson-polymorphic-deserialization
浙公网安备 33010602011771号