栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

System.Text.Json中可以进行多态反序列化吗?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

System.Text.Json中可以进行多态反序列化吗?

System.Text.Json中可以进行多态反序列化吗?

答案是肯定的 ,并 没有,这取决于你的意思是什么 “可能”

没有 多态的反序列化(相当于Newtonsoft.Json的

TypeNameHandling
)支持 内置
System.Text.Json
。这是因为阅读指定为JSON有效载荷(如在一个字符串的.NET类型名称
$type
是元数据属性)来创建你的对象
不推荐使用 ,因为它引入了潜在的安全隐患(见https://github.com/dotnet/corefx/ Issues /
41347#issuecomment-535779492了解更多信息)。

允许有效负载指定自己的类型信息是Web应用程序中漏洞的常见来源。

然而, 通过创建一个以增加自己的多态反序列化方式支持

JsonConverter<T>
,所以在这个意义上说,这是可能的。

该文档显示了一个使用 类型鉴别器 属性的方法的示例:https : //docs.microsoft.com/zh-
cn/dotnet/standard/serialization/system-text-json-converters-how-to#support-
多态反序列化

让我们来看一个例子。

假设您有一个基类和几个派生类:

public class baseClass{    public int Int { get; set; }}public class DerivedA : baseClass{    public string Str { get; set; }}public class DerivedB : baseClass{    public bool Bool { get; set; }}

您可以创建以下代码

JsonConverter<baseClass>
,该代码在序列化时写入类型识别符,然后读取以识别要反序列化的类型。您可以在上注册该转换器
JsonSerializerOptions

public class baseClassConverter : JsonConverter<baseClass>{    private enum TypeDiscriminator    {        baseClass = 0,        DerivedA = 1,        DerivedB = 2    }    public override bool CanConvert(Type type)    {        return typeof(baseClass).IsAssignableFrom(type);    }    public override baseClass Read(        ref Utf8JsonReader reader,        Type typeToConvert,        JsonSerializerOptions options)    {        if (reader.TokenType != JsonTokenType.StartObject)        { throw new JsonException();        }        if (!reader.Read()     || reader.TokenType != JsonTokenType.PropertyName     || reader.GetString() != "TypeDiscriminator")        { throw new JsonException();        }        if (!reader.Read() || reader.TokenType != JsonTokenType.Number)        { throw new JsonException();        }        baseClass baseClass;        TypeDiscriminator typeDiscriminator = (TypeDiscriminator)reader.GetInt32();        switch (typeDiscriminator)        { case TypeDiscriminator.DerivedA:     if (!reader.Read() || reader.GetString() != "Typevalue")     {         throw new JsonException();     }     if (!reader.Read() || reader.TokenType != JsonTokenType.StartObject)     {         throw new JsonException();     }     baseClass = (DerivedA)JsonSerializer.Deserialize(ref reader, typeof(DerivedA));     break; case TypeDiscriminator.DerivedB:     if (!reader.Read() || reader.GetString() != "Typevalue")     {         throw new JsonException();     }     if (!reader.Read() || reader.TokenType != JsonTokenType.StartObject)     {         throw new JsonException();     }     baseClass = (DerivedB)JsonSerializer.Deserialize(ref reader, typeof(DerivedB));     break; default:     throw new NotSupportedException();        }        if (!reader.Read() || reader.TokenType != JsonTokenType.EndObject)        { throw new JsonException();        }        return baseClass;    }    public override void Write(        Utf8JsonWriter writer,        baseClass value,        JsonSerializerOptions options)    {        writer.WriteStartObject();        if (value is DerivedA derivedA)        { writer.WriteNumber("TypeDiscriminator", (int)TypeDiscriminator.DerivedA); writer.WritePropertyName("Typevalue"); JsonSerializer.Serialize(writer, derivedA);        }        else if (value is DerivedB derivedB)        { writer.WriteNumber("TypeDiscriminator", (int)TypeDiscriminator.DerivedB); writer.WritePropertyName("Typevalue"); JsonSerializer.Serialize(writer, derivedB);        }        else        { throw new NotSupportedException();        }        writer.WriteEndObject();    }}

这是序列化和反序列化的样子(包括与Newtonsoft.Json的比较):

private static void PolymorphicSupportComparison(){    var objects = new List<baseClass> { new DerivedA(), new DerivedB() };    // Using: System.Text.Json    var options = new JsonSerializerOptions    {        Converters = { new baseClassConverter() },        WriteIndented = true    };    string jsonString = JsonSerializer.Serialize(objects, options);    Console.WriteLine(jsonString);        var roundTrip = JsonSerializer.Deserialize<List<baseClass>>(jsonString, options);    // Using: Newtonsoft.Json    var settings = new Newtonsoft.Json.JsonSerializerSettings    {        TypeNameHandling = Newtonsoft.Json.TypeNameHandling.Objects,        Formatting = Newtonsoft.Json.Formatting.Indented    };    jsonString = Newtonsoft.Json.JsonConvert.SerializeObject(objects, settings);    Console.WriteLine(jsonString);        var originalList = JsonConvert.DeserializeObject<List<baseClass>>(jsonString, settings);    Debug.Assert(originalList[0].GetType() == roundTrip[0].GetType());}


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/485473.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号