对象列表的JSON反序列化

本文关键字:反序列化 JSON 列表 对象 | 更新日期: 2023-09-27 18:24:56

我正在尝试将客户端和服务器之间发送的对象序列化和反序列化为JSON。我将来自客户端的所有消息封装在一个简单的请求对象中,该对象看起来像这样:

class Request
{
    public string Command { get; set; }
    public object[] Arguments { get; set; }
}

Arguments数组可以是所选命令所需的任何类型的对象。然后在服务器上反序列化,并希望Arguments数组中具有相同类型对象的Request看起来完全相同。

我已经尝试过.Net和Json.Net中包含的JavascriptSerialization,但它们在参数列表中的某些对象类型方面都有问题。字符串、int和其他基本的东西工作得很好,但例如Guid总是在反序列化后作为字符串弹出。

当使用Json.Net时,其他复杂对象会变成"JObject"。(我得到了@jlvaquero的帮助来解决这个问题。)

有人建议如何使反序列化尽可能正确吗?

示例:https://dotnetfiddle.net/V3HKol

对象列表的JSON反序列化

您需要使用TypeNameHandling设置。

如果JSON字符串在每个序列化对象中都包含运行时类型,则JSON.Net将其反序列化为匹配运行时类型。

using System;
using Newtonsoft.Json;
public class Program
{
    public static void Main()
    {
        Request r = new Request();
        r.Arguments[0] = new TestObject("111111");
        r.Arguments[1] = new TestObject("222222");
        string output = JsonConvert.SerializeObject(r, Formatting.Indented, new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.All
});
        Console.WriteLine(output);
        Request deserializedr = JsonConvert.DeserializeObject<Request>(output, new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.Auto
});
        Console.WriteLine(deserializedr.Command);
        Console.WriteLine(((TestObject)(deserializedr.Arguments[0])).Name );
        Console.WriteLine(((TestObject)(deserializedr.Arguments[0])).ID);
        Console.WriteLine(((TestObject)(deserializedr.Arguments[1])).Name );
        Console.WriteLine(((TestObject)(deserializedr.Arguments[1])).ID);
        Console.ReadKey();
    }
}
    public class Request
{
        public Request(){
            Command = "boquepasa";
            Arguments = new Object[2];
        }
    public string Command { get; set; }
    public object[] Arguments { get; set; }
}
public class TestObject
{
    public TestObject(string name)
    {
        ID = Guid.NewGuid();
        Name = name;
    }
    public string Name { get; set; }
    public Guid ID { get; set; }
}

输出:

{
  "$type": "Request, ConsoleApplication1",
  "Command": "boquepasa",
  "Arguments": {
    "$type": "System.Object[], mscorlib",
    "$values": [
      {
        "$type": "TestObject, ConsoleApplication1",
        "Name": "111111",
        "ID": "739479b5-9034-451f-9b58-abcf4c7671f1"
      },
      {
        "$type": "TestObject, ConsoleApplication1",
        "Name": "222222",
        "ID": "f6ea82d5-fa3d-481d-812e-baf9fab49a86"
      }
    ]
  }
}
boquepasa
111111
739479b5-9034-451f-9b58-abcf4c7671f1
222222
f6ea82d5-fa3d-481d-812e-baf9fab49a86

如果执行r.Arguments[2] = Guid.NewGuid() JSON.Net,则将其反序列化为String。我在Newtonsoft.Json报告中打开了一个问题,在等待响应的同时,我已经分叉了原始github存储库,在Object Array支持中添加了Guid。我的回购在这里,可以很好地处理这个特定问题,但除了这个例子之外,它还没有经过测试,所以使用它的风险自负。

您应该能够通过将Json.Net中的JsonSerializerSettings设置为来包含类型信息

new JsonSerializerSettings
{
     TypeNameHandling = TypeNameHandling.All
}

这将在json字符串上包含一个名为$type的新属性,该属性在反序列化对象时为json.Net提供提示。

您需要在序列化的两侧都使用这个JsonSerializerSettings才能正常工作。

更多信息请点击此处:http://www.newtonsoft.com/json/help/html/serializetypenamehandling.htm

示例

    class ExampleClass
    {
        public string StringProperty { get; set; }
        public int IntProperty { get; set; }
    }
    class Program
    {
        static void Main(string[] args)
        {
            var objects = new object[]
            {
                new ExampleClass(),
                new StringBuilder()
            };
            var json = JsonConvert.SerializeObject(objects, new JsonSerializerSettings
            {
                TypeNameHandling = TypeNameHandling.All
            });
            Console.WriteLine(json);
            var deserializedObjects = JsonConvert.DeserializeObject(json, new JsonSerializerSettings
            {
                TypeNameHandling = TypeNameHandling.All
            });
            foreach (var type in (object[])deserializedObjects)
            {
                Console.WriteLine(type.GetType());
            }
            Console.ReadKey();
        }
    }

输出

{
    "$type": "System.Object[], mscorlib",
    "$values": [{
        "$type": "ConsoleApplication8.ExampleClass, ConsoleApplication8",
        "StringProperty": null,
        "IntProperty": 0
    },
    {
        "$type": "System.Text.StringBuilder, mscorlib",
        "m_MaxCapacity": 2147483647,
        "Capacity": 16,
        "m_StringValue": "",
        "m_currentThread": 0
    }]
}
ConsoleApplication8.ExampleClass
System.Text.StringBuilder