我通过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替换为第二个项目名称,除了替换之外的任何解决方法吗?
答案 0 :(得分:1)
要回答您更新的问题,&#34;如何在使用Json.NET&#34;在不同.Net程序集之间交换包含$type
信息的JSON数据时重新映射程序集名称,您有以下几种选择:< / p>
最简单的方法是将有问题的类型提取到共享DLL中,并从两个程序集中引用该DLL。这解决了问题,也减少了代码重复。
如果你不能这样做,你需要编写自己的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。
要完全省略程序集名称和命名空间,可以使用How to create a SerializationBinder for the Binary Formatter that handles the moving of types from one assembly and namespace to another中的绑定程序进行序列化和反序列化。
最后,您可以考虑切换到使用合同名称而不是原始.Net类型名称间接交换类型信息的Json serialization for Object Data Type。虽然数据契约序列化程序通常不如Json.NET灵活,但在这种情况下,基于合同的类型信息交换可能更合适。例如,请参阅DataContractJsonSerializer
。