JSon.NET反序列化对象不起作用

时间:2014-10-18 00:16:40

标签: c# json sockets serialization json.net

所以我有一个使用这个类进行通信的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。

1 个答案:

答案 0 :(得分:1)

让我们首先考虑您的JSON输入:

{
    "dcReason": 4,
    "payload": {
        "msg": "hi"
    }
}

使用Json.NET,您有两种反序列化JSON数据的关键方法。你可以:

  1. 将其反序列化为特定的具体类型
  2. 您可以将其反序列化为通用JToken类型。 (在您的情况下,它实例化JObject - JToken的子类 - 因为JSON.Net认识到JSON输入指定了一个对象,而不是基本类型或数组)
  3. 在你的情况下,你实际上最终得到了两种方法的混合。由于您为根对象指定了特定类型,因此它返回了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并期望所有用法都得到修复。使用字符串时,这显然不太健壮。