JsonConverter如何反序列化为通用对象

时间:2016-02-10 20:52:41

标签: c# json object json.net uwp

我通过webapi发送此结构:

[DataContract]
public class PacketData
{
    public enum Opcodes
    {
        Hello = 0x00,
        Close = 0x01,
        Serial = 0x02,
        GPIO = 0x04
    }

    [DataMember]
    public object Data { get; private set; }
    [DataMember]
    public Opcodes Opcode { get; private set; }

    public PacketData(Opcodes opcode, object data)
    {
        Data = data;
        Opcode = opcode;
    }
}

我的问题是我在发送它时设置在服务器端我分配给几个类的数据。 CustomClass1,CustomClass2

现在反序列化我得到的是对象字符串,而不是:

{\r\n  \"Cmd\": 5,\r\n  \"BaudRates\": [\r\n    2400,\r\n    4800,\r\n    9600,\r\n    19200,\r\n    38400,\r\n    57600,\r\n    115200\r\n  ],\r\n  \"SerialPorts\": null,\r\n  \"IsOpen\": false,\r\n  \"BaudRate\": 0,\r\n  \"PortName\": null,\r\n  \"WriteCMD\": null,\r\n  \"WriteDATA\": null,\r\n  \"Read\": null\r\n}

所以Data是字符串而不是类或C#经典对象类型 并且有问题我不知道如何从字符串中识别它的CustomClass1或CustomClass2。

有任何想法如何解决这个问题?

感谢。

编辑:包括反序列化和序列化

[HttpGet("Send", Name = "Send")]
public IActionResult Send()
{
    return Ok(WebAPI.Send(), HttpStatusCode.OK);
}

    public IEnumerable<string> Send()
    {
        List<string> packets = new List<string>();

        foreach (PacketData packet in StaticConfig.SendStack.ToArray())
            packets.Add(JsonConvert.SerializeObject(packet));

        return packets.ToArray();
    }

这是反序列化:

                string json = await client.GetStringAsync(new Uri("http://localhost:5000/api/Send"));

                string[] jsonArray = JsonConvert.DeserializeObject<string[]>(json);

                if (jsonArray.Length == 0)
                    Task.Delay(100).Wait();

                List<PacketData> packets = new List<PacketData>();

                foreach (string j in jsonArray)
                    packets.Add(JsonConvert.DeserializeObject<PacketData>(j));

                foreach (PacketData packet in packets)
                {
                    string p = packet.Data.ToString();

                    bool a = packet.Data is PacketSerialModel; // returns false

                    HandleReceivedData(this, new ReceivedDataArgs(packet));
                }

编辑2: 那我想要什么?

我想在PacketData.Data中找回提到的字符串然后我可以使用这样的东西:

if(packet.Data is CustomClass1)
{
}
else if(packet.Data is CustomClass2)
{
  var b = packetData as CustomClass2;
  //...
}

目前我的packet.Data是字符串,我需要在这个对象上创建属性,并根据json为它们设置值。

EDIT3: 现在使用

JsonSerializerSettings()
{ TypeNameHandling = TypeNameHandling.Auto }

完美地工作,但我必须替换传入的json字符串项目名称 比如下面的字符串:

["{\"Data\":{\"$type\":\"Shared.PacketSerialModel, ASP_MVC\",\"Cmd\":5,\"BaudRates\":[2400,4800,9600,19200,38400,57600,115200],\"SerialPorts\":null,\"IsOpen\":false,\"BaudRate\":0,\"PortName\":null,\"WriteCMD\":null,\"WriteDATA\":null,\"Read\":null},\"Opcode\":2}"]

我必须将ASP_MVC替换为第二个项目名称,除了替换之外的任何解决方法吗?

1 个答案:

答案 0 :(得分:1)

要回答您更新的问题,&#34;如何在使用Json.NET&#34;在不同.Net程序集之间交换包含$type信息的JSON数据时重新映射程序集名称,您有以下几种选择:< / p>

  1. 最简单的方法是将有问题的类型提取到共享DLL中,并从两个程序集中引用该DLL。这解决了问题,也减少了代码重复。

  2. 如果你不能这样做,你需要编写自己的SerializationBinder,可能继承自Json.NET的DefaultSerializationBinder,如文档中所述:{{ 3}}。如果您的课程通用,则只需重新映射assemblyName

    public class SimpleAssemblyMappingSerializationBinder : DefaultSerializationBinder
    {
        readonly string oldAssemblyName;
        readonly string newAssemblyName;
    
        public SimpleAssemblyMappingSerializationBinder(string oldAssemblyName, string newAssemblyName)
        {
            this.oldAssemblyName = oldAssemblyName;
            this.newAssemblyName = newAssemblyName;
        }
    
        public override Type BindToType(string assemblyName, string typeName)
        {
            if (assemblyName == oldAssemblyName)
                assemblyName = newAssemblyName;
            return base.BindToType(assemblyName, typeName);
        }
    }
    

    对于类似的活页夹,请参阅Custom SerializationBinder

    但是如果您的类 是通用的(例如,如果Data有时是List<CustomClass3>),则需要解析类型内的Handling namespace changes with TypeNameHandling.All名称。有关如何执行此操作的说明,请参阅generic parameters。那个问题是BinaryFormatter,但答案也适用于Json.NET。

  3. 要完全省略程序集名称和命名空间,可以使用How to create a SerializationBinder for the Binary Formatter that handles the moving of types from one assembly and namespace to another中的绑定程序进行序列化和反序列化。

  4. 最后,您可以考虑切换到使用合同名称而不是原始.Net类型名称间接交换类型信息的Json serialization for Object Data Type。虽然数据契约序列化程序通常不如Json.NET灵活,但在这种情况下,基于合同的类型信息交换可能更合适。例如,请参阅DataContractJsonSerializer