所以我有一个使用这个类进行通信的Client-Server应用程序,它包含一个对象,所以我可以在服务器和客户端之间发送任何类型的数据:
public class comObj
{
public eDisconnectedReason dcReason;
public object payload;
}
在通过Socket发送之前,我将使用JSon.Net对其进行序列化,例如:
string jsonString = JsonConvert.SerializeObject((new Common.comObj() { dcReason = Server.disconnectedReason, payload = Data }), Formatting.None);
现在服务器正好接收客户端发送的字符串:
sent string: "{\"dcReason\":4,\"payload\":{\"msg\":\"hi\"}}"
received string: "{\"dcReason\":4,\"payload\":{\"msg\":\"hi\"}}"
然而,当我尝试将收到的字符串反序列化为原始的comObj:
时Common.comObj rcvdObj = JsonConvert.DeserializeObject<Common.comObj>(rcvdString);
rcvdObj.payload的类型为Newtonsoft.Json.Linq.JObject而不是object。
答案 0 :(得分:1)
让我们首先考虑您的JSON输入:
{
"dcReason": 4,
"payload": {
"msg": "hi"
}
}
使用Json.NET,您有两种反序列化JSON数据的关键方法。你可以:
JToken
类型。 (在您的情况下,它实例化JObject
- JToken
的子类 - 因为JSON.Net认识到JSON输入指定了一个对象,而不是基本类型或数组)在你的情况下,你实际上最终得到了两种方法的混合。由于您为根对象指定了特定类型,因此它返回了comObj
的实例。由于您只是将object
指定为属性payload
的类型,因此Json.NET尽了最大努力并简单地恢复为选项2)并为您提供了JObject
的实例,其中包含数据例如msg
。
您有两种方法可以解决您的问题。你可以:
payload
属性作为JObject
进行询问,就像您在未使用选项1时必须为整个JSON正文所做的那样。 payload
属性的具体类型。我强烈推荐这种方法,因为它更加类型安全且更易于使用。要实现前者,您可以使用诸如o["msg"]
之类的设备 - 基本上就像字典一样。
要实现后者 - 我建议 - 只需为payload
定义一个类型。换句话说,将代码更改为:
public class comObj
{
public eDisconnectedReason dcReason;
public Payload payload;
}
public class Payload
{
public string msg { get; set; }
}
现在,当您反序列化JSON时,您将能够使用以下语法:
Console.WriteLine(rcvdObj.payload.msg);
而且 - 重要的是 - 如果您以后决定将JSON有效负载中的msg
重命名为message
,那么您将能够正确重构该属性{有效负载{1}}到msg
并期望所有用法都得到修复。使用字符串时,这显然不太健壮。