对象列表的JSON反序列化
本文关键字:反序列化 JSON 列表 对象 | 更新日期: 2023-09-27 18:24:56
我正在尝试将客户端和服务器之间发送的对象序列化和反序列化为JSON。我将来自客户端的所有消息封装在一个简单的请求对象中,该对象看起来像这样:
class Request
{
public string Command { get; set; }
public object[] Arguments { get; set; }
}
Arguments数组可以是所选命令所需的任何类型的对象。然后在服务器上反序列化,并希望Arguments数组中具有相同类型对象的Request看起来完全相同。
我已经尝试过.Net和Json.Net中包含的JavascriptSerialization,但它们在参数列表中的某些对象类型方面都有问题。字符串、int和其他基本的东西工作得很好,但例如Guid总是在反序列化后作为字符串弹出。
有人建议如何使反序列化尽可能正确吗?
示例:https://dotnetfiddle.net/V3HKol
您需要使用TypeNameHandling设置。
如果JSON字符串在每个序列化对象中都包含运行时类型,则JSON.Net将其反序列化为匹配运行时类型。
using System;
using Newtonsoft.Json;
public class Program
{
public static void Main()
{
Request r = new Request();
r.Arguments[0] = new TestObject("111111");
r.Arguments[1] = new TestObject("222222");
string output = JsonConvert.SerializeObject(r, Formatting.Indented, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All
});
Console.WriteLine(output);
Request deserializedr = JsonConvert.DeserializeObject<Request>(output, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
});
Console.WriteLine(deserializedr.Command);
Console.WriteLine(((TestObject)(deserializedr.Arguments[0])).Name );
Console.WriteLine(((TestObject)(deserializedr.Arguments[0])).ID);
Console.WriteLine(((TestObject)(deserializedr.Arguments[1])).Name );
Console.WriteLine(((TestObject)(deserializedr.Arguments[1])).ID);
Console.ReadKey();
}
}
public class Request
{
public Request(){
Command = "boquepasa";
Arguments = new Object[2];
}
public string Command { get; set; }
public object[] Arguments { get; set; }
}
public class TestObject
{
public TestObject(string name)
{
ID = Guid.NewGuid();
Name = name;
}
public string Name { get; set; }
public Guid ID { get; set; }
}
输出:
{
"$type": "Request, ConsoleApplication1",
"Command": "boquepasa",
"Arguments": {
"$type": "System.Object[], mscorlib",
"$values": [
{
"$type": "TestObject, ConsoleApplication1",
"Name": "111111",
"ID": "739479b5-9034-451f-9b58-abcf4c7671f1"
},
{
"$type": "TestObject, ConsoleApplication1",
"Name": "222222",
"ID": "f6ea82d5-fa3d-481d-812e-baf9fab49a86"
}
]
}
}
boquepasa
111111
739479b5-9034-451f-9b58-abcf4c7671f1
222222
f6ea82d5-fa3d-481d-812e-baf9fab49a86
如果执行r.Arguments[2] = Guid.NewGuid()
JSON.Net,则将其反序列化为String
。我在Newtonsoft.Json报告中打开了一个问题,在等待响应的同时,我已经分叉了原始github存储库,在Object Array
支持中添加了Guid
。我的回购在这里,可以很好地处理这个特定问题,但除了这个例子之外,它还没有经过测试,所以使用它的风险自负。
您应该能够通过将Json.Net中的JsonSerializerSettings
设置为来包含类型信息
new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All
}
这将在json字符串上包含一个名为$type
的新属性,该属性在反序列化对象时为json.Net提供提示。
您需要在序列化的两侧都使用这个JsonSerializerSettings
才能正常工作。
更多信息请点击此处:http://www.newtonsoft.com/json/help/html/serializetypenamehandling.htm
示例
class ExampleClass
{
public string StringProperty { get; set; }
public int IntProperty { get; set; }
}
class Program
{
static void Main(string[] args)
{
var objects = new object[]
{
new ExampleClass(),
new StringBuilder()
};
var json = JsonConvert.SerializeObject(objects, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All
});
Console.WriteLine(json);
var deserializedObjects = JsonConvert.DeserializeObject(json, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All
});
foreach (var type in (object[])deserializedObjects)
{
Console.WriteLine(type.GetType());
}
Console.ReadKey();
}
}
输出
{
"$type": "System.Object[], mscorlib",
"$values": [{
"$type": "ConsoleApplication8.ExampleClass, ConsoleApplication8",
"StringProperty": null,
"IntProperty": 0
},
{
"$type": "System.Text.StringBuilder, mscorlib",
"m_MaxCapacity": 2147483647,
"Capacity": 16,
"m_StringValue": "",
"m_currentThread": 0
}]
}
ConsoleApplication8.ExampleClass
System.Text.StringBuilder