首页 > 其他分享 >system.text.Json 针对继承多态类型的集合,使用自定义Converter,进行json序列化

system.text.Json 针对继承多态类型的集合,使用自定义Converter,进行json序列化

时间:2024-09-23 09:45:06浏览次数:8  
标签:序列化 obj 自定义 多态 var new property type public

测试类:

[JsonConverter(typeof(PersonConverter))]
  public class Person
  {
      public string FirstName { get; set; }
      public string LastName { get; set; }
  }

  [JsonConverter(typeof(PersonConverter))]
  public class Employee : Person
  {
      public string Department { get; set; }
      public string JobTitle { get; set; }
  }
  [JsonConverter(typeof(PersonConverter))]
  public class Artist : Person
  {
      public string Skill { get; set; }
  }

  

自定义Converter:
public class PersonConverter : JsonConverter<Person>
{
    public override Person Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        JsonDocument.TryParseValue(ref reader, out var doc);
        var elm = doc.RootElement;
        elm.TryGetProperty("isBase", out var jEl);
        elm.TryGetProperty("typeName", out var typeEl);
        elm.TryGetProperty("obj", out var objEl);
      
        var typeStr = typeEl.GetString();
        var type = Type.GetType(typeStr);
        var objStr = objEl.GetRawText();
        var dic = JsonSerializer.Deserialize<Dictionary<string, string>>(objStr);

        var obj = ToObject(dic, type);
        return obj as Person;

    }

    public override bool CanConvert(Type typeToConvert)
    {
        if (typeToConvert == typeof(Person)) return true;
        if (typeToConvert.BaseType == typeof(Person)) return true;
        return false;
    }

    public override void Write(Utf8JsonWriter writer, Person value, JsonSerializerOptions options)
    {
        var type = value.GetType();

        var dic = new
        {
            typeName = type.FullName,
            obj = ToDictionary(value),

        };
        JsonSerializer.Serialize(writer, dic, options);
    }

    public Dictionary<string, object> ToDictionary(object obj)
    {
        if (obj == null)
            throw new ArgumentNullException(nameof(obj));

        var dictionary = new Dictionary<string, object>();
        foreach (var property in obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
        {
            if (property.CanRead)
            {
                dictionary[property.Name] = property.GetValue(obj, null);
            }
        }
        return dictionary;
    }

    public T ToObject<T>(Dictionary<string, object> source) where T : class, new()
    {
        T result = new T();
        Type type = typeof(T);

        foreach (KeyValuePair<string, object> item in source)
        {
            PropertyInfo property = type.GetProperty(item.Key);
            if (property != null && property.CanWrite)
            {
                property.SetValue(result, item.Value, null);
            }
        }

        return result;
    }

    public object ToObject(IDictionary<string, string> source, Type type)
    {
        var result = Activator.CreateInstance(type);

        foreach (KeyValuePair<string, string> item in source)
        {
            PropertyInfo property = type.GetProperty(item.Key);
            if (property != null && property.CanWrite)
            {
                property.SetValue(result, item.Value, null);
            }
        }

        return result;
    }
}

  入口方法:

static void Main(string[] args)
{
    Console.WriteLine("Hello World!");
    List<Person> people = new List<Person>
        {
            new Employee(){Department="test part",
            FirstName="Hello",
            LastName="L",
            JobTitle="engineer"},
            new Person()
            {
            FirstName="ooook",
            LastName="is not",
            },
            new Artist()
            {
            FirstName="oooo",
            LastName="is not ooo",
            Skill="coding"
            },
        };
    var str = JsonSerializer.Serialize(people);
    Console.WriteLine(str);
    var pes = JsonSerializer.Deserialize<List<Person>>(str);
}

  

思路就是:转换成特定的类,然后需要借助Dictionary转换,不然直接使用serialize会出现循环调用,或者直接再引用一个newTonsoft.json取代dictionnary与对象转换的方法,不过那样我感觉不太好。针对继承类型的集合序列化,反序列化,子类字段不缺失,值也不缺失。

标签:序列化,obj,自定义,多态,var,new,property,type,public
From: https://www.cnblogs.com/HelloQLQ/p/18426418

相关文章

  • Java反序列化利用链篇 | JdbcRowSetImpl利用链分析
    JdbcRowSetImpl利用链前言首先说明一下:利用链都有自己的使用场景,要根据场景进行选择不同的利用链。JdbcRowSetImpl利用链用于fastjson反序列化漏洞中。为什么?因为fastjson会在反序列化类时自动调用set开头的方法(不一定是setter方法),而JdbcRowSetImpl中存在一个set开头的方法,即......
  • Java反序列化利用链篇 | CC1链_全网最菜的分析思路【本系列文章的分析重点】
    CC1链_全网最菜的分析思路1你必须知道的点1.1反序列化利用链的起点是readObject()方法Java的序列化机制允许将对象的状态保存到一个字节流中,之后可以从这个字节流中恢复(或“反序列化”)出对象。这个过程中,ObjectInputStream类负责读取这些字节流,并尝试根据包含的类型信息重新......
  • Java反序列化调用链分析系列 | URLDNS链
    URLDNS链URLDNS链是java通过反序列化发起dns请求的利用链。一般用于测试反序列化漏洞。该链比较简单,利用链也比较短。其中入口类为HashMap,执行类为URLStreamHandler的hashCode()方法。整个调用链如下:HashMap.readObject()HashMap.putVal()HashMap.hash()URL.hashCode()......
  • map&unordered_map<key,value>key使用自定义类的要求
    std::unordered_map的键要求:std::unordered_map是基于哈希表的数据结构。它要求键类型必须支持哈希计算,也就是必须有对应的std::hash函数。另外,键类型还必须支持相等比较(通过operator==)。如果键类型没有定义哈希函数(例如你自定义的Json类型),std::unordered_map就无......
  • 数据处理与统计分析篇-day08-apply()自定义函数与分组操作
    一.自定义函数概述当Pandas自带的API不能满足需求,例如:我们需要遍历的对Series中的每一条数据/DataFrame中的一列或一行数据做相同的自定义处理,就可以使用Apply自定义函数apply函数可以接收一个自定义函数,可以将Series对象的逐个值或DataFrame的行/列数据传递给自......
  • C++从入门到起飞之——多态 全方位剖析!
    ......
  • fastjson反序列化漏洞
    fastjson将java中的类和json相互转化的一个工具.简单使用javabean类转jsonpublicclassFastjsonTest{publicstaticvoidmain(String[]args){Useruser=newUser();Stringjson=JSON.toJSONString(user);System.out.println(json);......
  • 解释器模式:如何实现一个自定义配置规则功能?
    解释器模式使用频率不算高,通常用来描述如何构建一个简单“语言”的语法解释器。它只在一些非常特定的领域被用到,比如编译器、规则引擎、正则表达式、SQL解析等。不过,了解它的实现原理同样很重要,能帮助我们思考如何通过更简洁的规则来表示复杂的逻辑。一、模式原理分析解释器模式......
  • 如何使用 AWS 部署带有自定义域的 React 项目?
    使用aws(amazonwebservices)等云提供商通过自定义域部署react应用程序可能看起来令人畏惧,但当分解为可管理的步骤时,它就很简单。在本文中,我们将指导您完成从构建应用程序到使其在您的自定义域上运行的整个过程。当您准备好与世界分享您的react项目时,使用自定义域部署它可以为......
  • 在 React 中创建自定义 Hook 的最佳技巧
    react的自定义hooks是从组件中删除可重用功能的有效工具。它们支持代码中的dry(不要重复)、可维护性和整洁性。但开发有用的自定义钩子需要牢牢掌握react的基本思想和推荐程序。在这篇文章中,我们将讨论在react中开发自定义钩子的一些最佳策略,并举例说明如何有效地应用它们。......