首页 文章

JSON反序列化对象列表

提问于
浏览 851 次
0

我试图将客户端和服务器之间发送的对象序列化和反序列化为JSON . 我将来自客户端的所有消息包装在一个简单的Request-object中,如下所示:

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

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

我已经尝试过.Net和Json.Net中包含的JavascriptSerialization,但两者都在参数列表中遇到了一些对象类型的问题 . 字符串,整数和其他基本内容很好地工作,但是例如Guid总是在反序列化后作为字符串弹出 .

使用Json.Net时,其他复杂对象变为“JObject” . (我从@jlvaquero那里得到了帮助来解决这个问题 . )

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

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

2 回答

  • -1

    您需要使用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 repoisotry中打开了一个问题,当我们等待响应时,我已经分叉了原始的github存储库,以便在 Object Array 支持中添加 Guid . 我的回购是here并且对这个特定问题很有效,但是除了这个例子之外没有测试过,所以使用它需要你自担风险 .

  • 1

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

    new JsonSerializerSettings
    {
         TypeNameHandling = TypeNameHandling.All
    }
    

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

    您需要在序列化的两侧使用 JsonSerializerSettings 才能使其正常工作 .

    更多信息:http://www.newtonsoft.com/json/help/html/serializetypenamehandling.htm

    Example

    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
    

相关问题