简体   繁体   中英

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:

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:

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

rcvdObj.payload is of type Newtonsoft.Json.Linq.JObject instead of object.

Let us start by considering your JSON input:

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

Using Json.NET you have two key ways of deserializing JSON data. You can:

  1. Deserialize it into a specific concrete type
  2. You can deserialize it into the generic JToken type. (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)

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 . 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 .

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).
  • Define a concrete type to represent the payload property. 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.

To achieve the latter -- which I would recommmend -- simply define a type for 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:

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. This is obviously less robust when using strings.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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