是否有C#库可以在一次调用中序列化.NET / C#强类型对象的树状结构?
编辑:我希望能够将JSON反序列化为类型对象的变量(或其他一些根类,但最好是对象),然后通过在此变量上调用GetType()来找出我刚刚反序列化的内容。所以每个类的每个实例的类型(bool / int / float / string除外)和每个List<>应该作为序列化JSON的一部分存储并自动检索。例如,如果我有这些C#类:
public class House
{
public int Number;
public List<Room> Rooms;
}
public class Room
{
public string Name;
public int Floor;
}
public class Bathroom : Room
{
public bool IsWet;
}
并初始化我的内存数据结构(注意我使用通用List类,而不是C#数组):
House myHouse = new House();
myHouse.Number = 13;
myHouse.Rooms = new List<Room>();
myHouse.Rooms.Add(new Room());
myHouse.Rooms[0].Name = "some room";
myHouse.Rooms[0].Floor = 0;
myHouse.Rooms.Add(new Bathroom());
myHouse.Rooms[0].Name = "other room";
myHouse.Rooms[0].Floor = 3;
myHouse.Rooms[0].IsWet = true;
之后我希望能够打出这样的话:
string jsonHouse = JSON.Serialize(myHouse);
在我的jsonHouse变量中获取(例如)这个(编辑:请注意,它将每个类的类型存储为JSON的一部分。还要注意存储在List中的派生类BathRoom的实例):
{
"class": "House",
"Number": "13",
"Rooms": [
{
"class": "Room",
"Name": "some room"
"Floor": "0",
},
{
"class": "Bathroom",
"Name": "other room"
"Floor": "0",
"IsWet": "true",
},
],
}
最后打电话给这样的话:
House copyOfMyHouse = JSON.Deserialize(jsonHouse);
编辑:这(右上方)的电话似乎有误导性。而不是上面的调用我应该期望反序列化是这样的:
object copyOfMyHouse = JSON.Desrialize(jsonHouse);
要在我的copyOfMyHouse变量(类型为object)中获取类House的实例,而不指定JSON.Deserialize我期望从哪种类型 - 我可能不会提前知道它。
获取myHouse变量的精确副本,其中包含List泛型类的实例,其中包含对Room类的两个实例的精确副本的引用。
是否有用C#编写的JSON序列化程序可以做到这一点?
优选FOSS / FLOSS可以(合法地)用于商业项目。
JSON字符串的格式可能与我上面作为示例使用的格式不同(例如,您提出的解决方案可能将List存储为JSON对象而不是数组,其他文本格式如BSON或XML是可接受的) 对任意数量的嵌套级别使用单次调用是必需的 - 否则任何JSON序列化程序都适合。 还需要将Dictionary序列化为JSON对象的能力。
如果我对我所寻找的内容的描述不清楚,请提出澄清问题。
答案 0 :(得分:2)
基本上,您希望序列化/反序列化包含派生类型的对象。解决方案是使用Json.NET。它非常简单易用。以下是您的数据示例:
House myHouse = new House();
myHouse.Number = 13;
myHouse.Rooms = new List<Room>();
Room room1 = new Room();
room1.Name = "some room";
room1.Floor = 0;
myHouse.Rooms.Add(room1);
Room room2 = new Room();
room2.Name = "other room";
room2.Floor = 3;
myHouse.Rooms.Add(room2);
Bathroom bathroom = new Bathroom();
bathroom.Name = "Bathroom";
bathroom.Floor = 2;
bathroom.IsWet = true;
myHouse.Rooms.Add(bathroom);
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.TypeNameHandling = TypeNameHandling.Auto;
string json = JsonConvert.SerializeObject(myHouse, settings);
Console.WriteLine("Serialize finished!");
House house = JsonConvert.DeserializeObject<House>(json, settings);
Console.WriteLine($"House number: {house.Number}; Total rooms: {house.Rooms.Count}");
foreach (Room room in house.Rooms)
{
if (room is Bathroom)
{
var temp = room as Bathroom;
Console.WriteLine($"Room name: {temp.Name}, wet: {temp.IsWet}");
}
else
{
Console.WriteLine($"Room name: {room.Name}");
}
}
Console.WriteLine("Deserialize finished!");
Console.ReadLine();
以下是序列化后获得的JSON字符串:
{
"Number": 13,
"Rooms": [
{
"Name": "some room",
"Floor": 0
},
{
"Name": "other room",
"Floor": 3
},
{
"$type": "DemoApp.Bathroom, DemoApp",
"IsWet": true,
"Name": "Bathroom",
"Floor": 2
}
]
}
在反序列化字符串后你得到了对象。
答案 1 :(得分:1)
Newtonsoft.JSON(有时称为JSON.NET)很好,可以作为NuGet包使用。然后你可以写下这样的东西:
var value = new { ID = 1, Name="test"};
string serialized = JsonConvert.SerializeObject(value);
反序列化(最简单的选项,但有很多好的方法可以做到):
result = JsonConvert.DeserializeObject(jsonResponse);
答案 2 :(得分:1)
虽然其他答案已经提供了很好的解决方案,但这里有一个使用DataContractJsonSerializer类。
var jsonString = "";
var jsonSerializer = new DataContractJsonSerializer(typeof(House));
using (var memoryStream = new MemoryStream())
using (var streamReader = new StreamReader(memoryStream))
{
jsonSerializer.WriteObject(memoryStream, myHouse);
memoryStream.Position = 0;
jsonString = streamReader.ReadToEnd();
}
Console.Write("JSON form of Person object: ");
Console.WriteLine(jsonString);