JSon.NET反序列化对象没有';不起作用

本文关键字:不起作用 NET 反序列化 对象 JSon | 更新日期: 2023-09-27 18:26:53

所以我有一个客户端-服务器应用程序,它使用这个类进行通信,它包含一个对象,所以我可以在服务器和客户端之间发送任何类型的数据:

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

在通过套接字发送之前,我将使用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。

JSon.NET反序列化对象没有';不起作用

让我们从考虑您的JSON输入开始:

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

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

  1. 将其反序列化为特定的具体类型
  2. 您可以将其反序列化为通用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,您将能够正确地将负载的属性msg重构为message,并期望所有用法都得到修复。当使用字符串时,这显然不那么健壮。