JsonConverter如何反序列化为通用对象 [英] JsonConverter how to deserialize to generic object

查看:166
本文介绍了JsonConverter如何反序列化为通用对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在通过webapi发送此结构:

I'm sending this structure through 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;
    }
}

而且我的问题是,我在发送数据时在服务器端进行了设置,并将其分配给Data少类ex. CustomClass1,CustomClass2

And my problem is that I set on server side when I sending it I assign to Data few class ex. CustomClass1, CustomClass2

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

Now on deserialize I get instead of object string which is:

{\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}

因此,数据是字符串而不是类或C#经典对象类型 还有一个问题,我不知道如何从字符串中识别出它的CustomClass1还是CustomClass2.

So Data is string instead of class or C# classic object type And there is problem I don't know how to recognize from string if its CustomClass1 or CustomClass2.

有什么办法解决这个问题吗?

Any ideas how to resolve this?

谢谢.

包括反序列化和序列化

[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));
                }

那我想要什么?

我想将提到的字符串返回到PacketData.Data中,然后可以使用类似以下的内容:

I would like to get back mentioned string into PacketData.Data then I can use something like this:

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

当前我的数据包.数据是字符串,我需要在此对象属性上创建并基于json为其设置值.

currently my packet.Data is string and I need to create on this object properties and set values to them based on json.

立即使用

JsonSerializerSettings()
{ TypeNameHandling = TypeNameHandling.Auto }

工作完美,但我必须替换传入的json字符串项目名称 就像下面的字符串一样:

Works perfectly, but I have to replace in incoming json string project name like in following string:

["{\"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替换为第二个项目名称,除了替换之外,还有其他解决方法吗?

I have to replace ASP_MVC to second project name, any workaround than replace?

推荐答案

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

To answer your updated question, "how do I remap assembly names when exchanging JSON data containing $type information between different .Net assemblies using Json.NET", you have a few options:

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

  1. The simplest would be to extract the types in question into a shared DLL and reference that DLL from both assemblies. This solves the problem and also reduces code duplication.

如果无法执行此操作,则需要编写自己的自定义SerializationBinder .如果您的类不是 通用类,则只需重新映射assemblyName:

If you cannot do this, you will need to write your own SerializationBinder, probably inheriting from Json.NET's DefaultSerializationBinder, as is described in the documentation: Custom SerializationBinder. If your classes are not generic, can simply remap the 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);
    }
}

有关类似的活页夹,请参见使用TypeNameHandling.All处理名称空间更改.全部

For a similar binder, see Handling namespace changes with TypeNameHandling.All.

但是,如果您的类通用的(例如,如果Data有时是List<CustomClass3>),则需要解析如何为二进制格式化程序创建SerializationBinder,以处理类型从一个程序集和名称空间移至另一个程序集和命名空间的操作.这个问题与BinaryFormatter有关,但答案也适用于Json.NET.

But if your classes are generic (for instance, if Data is sometimes a List<CustomClass3>), you will need to parse the generic parameters inside the type name. For an idea of how to do this see How to create a SerializationBinder for the Binary Formatter that handles the moving of types from one assembly and namespace to another. That question is about BinaryFormatter but the answer applies to Json.NET also.

要完全省略程序集名称和名称空间,可以使用用于对象数据类型的Json序列化,用于序列化和反序列化.

To omit the assembly name and namespace entirely, you could use the binder from Json serialization for Object Data Type for both serialization and deserialization.

最后,您可以考虑切换到如何使用未命名的集合反序列化JSON使用DataContractSerializer的类型.

Finally, you could consider switching to DataContractJsonSerializer which exchanges type information indirectly by using contract names rather than raw .Net type names. While the data contract serializer is generally less flexible than Json.NET, its contract-based exchange of type information may be more suitable in this case. See for instance How to deserialize JSON with unnamed collection of types using DataContractSerializer.

这篇关于JsonConverter如何反序列化为通用对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆