JSON反序列化对象列表

时间:2015-11-27 13:47:54

标签: c# json serialization

我正在尝试将客户端和服务器之间发送的对象序列化和反序列化为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 个答案:

答案 0 :(得分: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存储库,以便在Guid支持中添加Object Array。我的回购邮件是here,并且在此特定问题上运行良好,但未在此示例之外进行测试,因此请自行承担风险。

答案 1 :(得分:-1)

您应该能够通过将Json.Net中的JsonSerializerSettings设置为

来包含类型信息
new JsonSerializerSettings
{
     TypeNameHandling = TypeNameHandling.All
}

这将在名为$type的json字符串上包含一个新属性,在反序列化对象时为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