我正在尝试将客户端和服务器之间发送的对象序列化和反序列化为JSON。我将来自客户端的所有消息包装在一个简单的Request-object中,如下所示:
class Request
{
public string Command { get; set; }
public object[] Arguments { get; set; }
}
参数数组可以是所选命令所需的任何类型的对象。然后在服务器上反序列化并希望Request与Arguments数组中相同类型的对象看起来完全相同。
我已尝试过.Net和Json.Net中包含的JavascriptSerialization,但两者都在参数列表中遇到了一些对象类型的问题。 字符串,整数和其他基本内容很好地工作,但是例如Guid总是在反序列化后作为字符串弹出。
使用Json.Net时,其他复杂对象变为“JObject”。(我从@jlvaquero那里得到了帮助来解决这个问题。)
有没有人建议如何使反序列化尽可能正确?
答案 0 :(得分:1)
您需要使用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 repoisotry打开了一个问题,当我们等待响应时,我已经分叉了原始的github存储库,以便在Guid
支持中添加Object Array
。我的回购邮件是here,并且在此特定问题上运行良好,但未在此示例之外进行测试,因此请自行承担风险。
答案 1 :(得分:-1)
您应该能够通过将Json.Net中的JsonSerializerSettings
设置为
new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All
}
这将在名为$type
的json字符串上包含一个新属性,在反序列化对象时为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