【CSharp + JSON】序列化与反序列化基类集合中的子类对象

1. 测试数据结构

public interface IPerson
{
	string Name { get; set; }
}

public class Person : IPerson
{
	public string Name { get; set; }
	public Test Test { get; set; } = new Test();
}

public class Test
{
	public string AA { get; set; } = "AA";
	public string BB { get; set; } = "BB";
}

public class Student : Person
{
	public string Lesson { get; set; }
}

public class Teacher : Person
{
	public int Age { get; set; }
}

2. 类图

«BaseClass» Person +string Name +Test Test «DerivedClass» Student +string Lesson «DerivedClass» Teacher +int Age «PropertyClass» Test +string AA +string BB «Interface» IPerson +string Name

3. 直接序列化与反序列化

void Main()
{
	List<Person> list = new List<UserQuery.Person>();
	list.Add(new Person() { Name = "zhangsan" });
	list.Add(new Student() { Name = "lisi", Lesson = "123" });
	list.Add(new Teacher() { Name = "wangwu", Age = 33 });

	var settings = new JsonSerializerSettings
	{
		Formatting = Newtonsoft.Json.Formatting.Indented,
		NullValueHandling = NullValueHandling.Include,
		MissingMemberHandling = MissingMemberHandling.Ignore
	};
	var strJson = Newtonsoft.Json.JsonConvert.SerializeObject(list, settings);
	strJson.Dump();

	MethodOne(strJson);
}

private void MethodOne(string strJson)
{
	var settings = new JsonSerializerSettings
	{
		Formatting = Newtonsoft.Json.Formatting.Indented,
		NullValueHandling = NullValueHandling.Include,
		MissingMemberHandling = MissingMemberHandling.Ignore
	};

	var list = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Person>>(strJson, settings);
	list.Dump();
}

3.2 序列化结果

[
  {
    "Name": "zhangsan",
    "Test": {
      "AA": "AA",
      "BB": "BB"
    }
  },
  {
    "Lesson": "123",
    "Name": "lisi",
    "Test": {
      "AA": "AA",
      "BB": "BB"
    }
  },
  {
    "Age": 33,
    "Name": "wangwu",
    "Test": {
      "AA": "AA",
      "BB": "BB"
    }
  }
] 

3.2 反序列化结果

在这里插入图片描述

由结果可以发现,序列化能够正常的序列化各子类的所有属性,而反序列化的结果仅仅包含每个子类从基类继承的属性,而没有各子类的特定的属性。显然这并不是我们需要的。

4. 分步反序列化

为了执行分布反序列化,需要对原有的数据结构做写修改。需要在序列化时加入一个能够确定该类是啥类的唯一属性,这里使用类的GUID。修改后如下:

public interface IPerson
{
	string Name{get;set;}
	string GUID {get;set;}
}

public class Person : IPerson
{
	public string Name{get;set;}
	public string GUID {get;set;}  = System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.GUID.ToString();
	
	public Test test{get;set;} = new Test();
}

public class Test
{
	public string AA{get;set;} ="AA";
	public string BB{get;set;} ="BB";
}

public class Student : Person
{
	public string Lesson{get;set;}
	
	public Student()
	{
		this.GUID = System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.GUID.ToString();
	}
}

public class Teacher : Person
{
	public int Age{get;set;}
	
	public Teacher()
	{
		this.GUID = System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.GUID.ToString();
	}
}
void Main()
{
	List<Person> list = new List<UserQuery.Person>();
	list.Add(new Person() { Name = "zhangsan" });
	list.Add(new Student() {Name="lisi", Lesson="123"});
	list.Add(new Teacher(){Name="wangwu", Age = 33});
	
	var settings = new JsonSerializerSettings
	{
		Formatting = Newtonsoft.Json.Formatting.Indented,
		NullValueHandling = NullValueHandling.Include,
		MissingMemberHandling = MissingMemberHandling.Ignore
	};
	var strJson = Newtonsoft.Json.JsonConvert.SerializeObject(list, settings);
	strJson.Dump();
	
	MethodTwo(strJson);
}


private void MethodTwo(string strJson)
{
	Dictionary<string, Type> guids = new Dictionary<string, Type>();
	guids.Add(typeof(Person).GUID.ToString(), typeof(Person));
	guids.Add(typeof(Student).GUID.ToString(), typeof(Student));
	guids.Add(typeof(Teacher).GUID.ToString(), typeof(Teacher));

	List<Person> list = new List<UserQuery.Person>();
	using (StringReader sr = new StringReader(strJson))
	{
		JsonTextReader jtr = new JsonTextReader(sr);
		while (jtr.Read())
		{
			if (jtr.TokenType == JsonToken.StartObject)
			{
				JObject obj = JObject.Load(jtr);
				obj.ToString().Dump();
				foreach (var element in guids.Keys)
				{
					if (obj.Property("GUID").Value.ToString() == element)
					{
						list.Add((Person)Newtonsoft.Json.JsonConvert.DeserializeObject(obj.ToString(), guids[element]));
					}
				}

			}
		}
	}
	list.Dump();
}

4.1 序列化结果

[
  {
    "Name": "zhangsan",
    "GUID": "fe88be23-6d26-3315-9438-d788614a229d",
    "test": {
      "AA": "AA",
      "BB": "BB"
    }
  },
  {
    "Lesson": "123",
    "Name": "lisi",
    "GUID": "8cd8bae9-6962-3e9d-81db-3e8c534158e7",
    "test": {
      "AA": "AA",
      "BB": "BB"
    }
  },
  {
    "Age": 33,
    "Name": "wangwu",
    "GUID": "506f3728-33f8-3c37-ad2c-1b49247c4498",
    "test": {
      "AA": "AA",
      "BB": "BB"
    }
  }
]

4.2 反序列化结果

在这里插入图片描述

由结果可见,正确得到了每个子类的特有属性

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhy29563

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值