简体   繁体   English

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

[英]JSon.NET deserializing object doesn't work

So I have a Client-Server application that is using this class for communication, it contains an object so I can send any kind of data between server and client: 因此,我有一个使用此类进行通信的客户端-服务器应用程序,它包含一个对象,因此我可以在服务器和客户端之间发送任何类型的数据:

        public class comObj
        {
            public eDisconnectedReason dcReason;
            public object payload;
        }

Before sending it through the Socket I will serialize it using JSon.Net, eg: 在通过套接字发送之前,我将使用JSon.Net将其序列化,例如:

string jsonString = JsonConvert.SerializeObject((new Common.comObj() { dcReason = Server.disconnectedReason, payload = Data }), Formatting.None);

now the server receives exactly the string that was sent by the client: 现在服务器完全接收到客户端发送的字符串:

sent string: "{\"dcReason\":4,\"payload\":{\"msg\":\"hi\"}}"
received string: "{\"dcReason\":4,\"payload\":{\"msg\":\"hi\"}}"

however when I try to deserialize the received string into the original comObj: 但是,当我尝试将接收到的字符串反序列化为原始comObj时:

Common.comObj rcvdObj = JsonConvert.DeserializeObject<Common.comObj>(rcvdString);

rcvdObj.payload is of type Newtonsoft.Json.Linq.JObject instead of object. rcvdObj.payload的类型为Newtonsoft.Json.Linq.JObject,而不是object。

Let us start by considering your JSON input: 让我们首先考虑您的JSON输入:

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

Using Json.NET you have two key ways of deserializing JSON data. 使用Json.NET,您有两种反序列化JSON数据的关键方法。 You can: 您可以:

  1. Deserialize it into a specific concrete type 将其反序列化为特定的具体类型
  2. You can deserialize it into the generic JToken type. 您可以将其反序列化为通用JToken类型。 (In your case, it instantiates a JObject -- a subclass of JToken -- because JSON.Net recognized that the JSON input specified an object, as opposed to a primitive type or an array) (你的情况,它实例化一个JObject -的一个子类JToken -因为JSON.Net认识到,JSON输入指定的对象,而不是一个基本类型或阵列)

In your case, you actually ended up with a hybrid of both approaches. 在您的情况下,您实际上最终混合了这两种方法。 Since you specified a specific type for the root object, it returned an instance of comObj . 由于您为根对象指定了特定类型,因此它返回了comObj的实例。 Since you merely specified object as the type of the property payload , Json.NET did its best and simply reverted to option 2) and gave you an instance of JObject , which contains the data such as msg . 由于您仅将object指定为属性payload的类型,因此Json.NET会尽力而为,并简单地恢复为选项2),并为您提供一个JObject实例,其中包含msg等数据。

You have two options to solve your problem. 您有两种选择来解决您的问题。 You can: 您可以:

  • Interrogate the payload property as a JObject , like you would have had to do for the entire JSON body if you had not used option 1). payload属性查询为JObject ,就像如果您不使用选项1)一样,必须对整个JSON主体执行操作。
  • Define a concrete type to represent the payload property. 定义一个具体类型来表示payload属性。 I strongly recommend this approach, as it is considerably more typesafe and also easier to work with. 强烈建议使用这种方法,因为它更加类型安全,并且使用起来也更容易。

To achieve the former, you can use faclities such as o["msg"] -- essentially like a dictionary. 要实现前者,您可以使用诸如o["msg"] -本质上就像字典。

To achieve the latter -- which I would recommmend -- simply define a type for payload . 要实现后者(我建议),只需定义payload的类型。 In other words, change you code to: 换句话说,将您的代码更改为:

    public class comObj
    {
        public eDisconnectedReason dcReason;
        public Payload payload;
    }

    public class Payload 
    {
        public string msg { get; set; }
    }

Now when you deserialize your JSON, you'll be able to use the syntax: 现在,当您反序列化JSON时,就可以使用以下语法:

Console.WriteLine(rcvdObj.payload.msg);

And -- importantly -- if you later decide to rename msg in your JSON payload to, say, message you will be able to properly refactor the property msg of payload to message and expect all usages to be fixed. 而且-重要的是-如果您以后决定将JSON有效负载中的msg重命名为message那么您将能够正确地将有效负载的msg属性重构message并期望所有用法都将得到修复。 This is obviously less robust when using strings. 使用字符串时,这显然不那么健壮。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM