C# 客户端上的Json反序列化类结构
我无法在客户端端点上反序列化JSON数据。它接收的JSON数据如下:C# 客户端上的Json反序列化类结构,c#,json,deserialization,C#,Json,Deserialization,我无法在客户端端点上反序列化JSON数据。它接收的JSON数据如下: { "WaitForClientMessagesResult": [ { "__type": "KeepAliveMessage:#Data.WebGateway", "MessageId": 1, "Type": 0, "PositionInQueue": -1 } ] } [Kn
{
"WaitForClientMessagesResult": [
{
"__type": "KeepAliveMessage:#Data.WebGateway",
"MessageId": 1,
"Type": 0,
"PositionInQueue": -1
}
]
}
[KnownType(typeof(KeepAliveMessage))]
[DataContract]
public abstract class WebClientMessage
{
public WebClientMessage() { }
[DataMember]
public int MessageId { get; set; }
[DataMember]
public WebClientMessageType Type { get; set; }
}
[DataContract]
public class KeepAliveMessage : WebClientMessage
{
public KeepAliveMessage() { }
[DataMember]
public int PositionInQueue { get; set; }
}
[DataContract(Name = "WaitForClientMessagesResult", Namespace = "http://schemas.datacontract.org/2004/07/Data.WebGateway")]
public class WaitForClientMessagesResult
{
public WaitForClientMessagesResult() { }
[DataMember(Name = "WaitForClientMessagesResult")]
public WebClientMessage[] Messages { get; set; }
}
KeepAliveMessage
是WebResponseMessage
的派生类。该服务返回一个IEnumerable
我遇到这样的例外情况:
{
"WaitForClientMessagesResult": [
{
"__type": "KeepAliveMessage:#Data.WebGateway",
"MessageId": 1,
"Type": 0,
"PositionInQueue": -1
}
]
}
[KnownType(typeof(KeepAliveMessage))]
[DataContract]
public abstract class WebClientMessage
{
public WebClientMessage() { }
[DataMember]
public int MessageId { get; set; }
[DataMember]
public WebClientMessageType Type { get; set; }
}
[DataContract]
public class KeepAliveMessage : WebClientMessage
{
public KeepAliveMessage() { }
[DataMember]
public int PositionInQueue { get; set; }
}
[DataContract(Name = "WaitForClientMessagesResult", Namespace = "http://schemas.datacontract.org/2004/07/Data.WebGateway")]
public class WaitForClientMessagesResult
{
public WaitForClientMessagesResult() { }
[DataMember(Name = "WaitForClientMessagesResult")]
public WebClientMessage[] Messages { get; set; }
}
Newtonsoft.Json.JsonSerializationException:
无法将当前JSON对象(例如{“name”:“value”})反序列化为类型
'System.Collections.Generic.IEnumerable'1[
Red5 ProtoType.Models.WaitForClientMessagesResult]
因为该类型需要一个JSON数组(例如[1,2,3])才能正确反序列化
我尝试了多种方式调用反序列化:
- WaitForClientMessagesResult反序列化=JsonConvert.DeserializeObject(keepAliveResult)代码>
- WaitForClientMessagesResult[]反序列化=JsonConvert.DeserializeObject(keepAliveResult)代码>
IEnumerable反序列化=JsonConvert.DeserializeObject(keepAliveResult)代码>
{
"WaitForClientMessagesResult": [
{
"__type": "KeepAliveMessage:#Data.WebGateway",
"MessageId": 1,
"Type": 0,
"PositionInQueue": -1
}
]
}
[KnownType(typeof(KeepAliveMessage))]
[DataContract]
public abstract class WebClientMessage
{
public WebClientMessage() { }
[DataMember]
public int MessageId { get; set; }
[DataMember]
public WebClientMessageType Type { get; set; }
}
[DataContract]
public class KeepAliveMessage : WebClientMessage
{
public KeepAliveMessage() { }
[DataMember]
public int PositionInQueue { get; set; }
}
[DataContract(Name = "WaitForClientMessagesResult", Namespace = "http://schemas.datacontract.org/2004/07/Data.WebGateway")]
public class WaitForClientMessagesResult
{
public WaitForClientMessagesResult() { }
[DataMember(Name = "WaitForClientMessagesResult")]
public WebClientMessage[] Messages { get; set; }
}
像这样使用Keepalive:
{
"WaitForClientMessagesResult": [
{
"__type": "KeepAliveMessage:#Data.WebGateway",
"MessageId": 1,
"Type": 0,
"PositionInQueue": -1
}
]
}
[KnownType(typeof(KeepAliveMessage))]
[DataContract]
public abstract class WebClientMessage
{
public WebClientMessage() { }
[DataMember]
public int MessageId { get; set; }
[DataMember]
public WebClientMessageType Type { get; set; }
}
[DataContract]
public class KeepAliveMessage : WebClientMessage
{
public KeepAliveMessage() { }
[DataMember]
public int PositionInQueue { get; set; }
}
[DataContract(Name = "WaitForClientMessagesResult", Namespace = "http://schemas.datacontract.org/2004/07/Data.WebGateway")]
public class WaitForClientMessagesResult
{
public WaitForClientMessagesResult() { }
[DataMember(Name = "WaitForClientMessagesResult")]
public WebClientMessage[] Messages { get; set; }
}
我试图使WebClientMessage
成为WaitForClientMessagesResult
[DataContract]
public class WaitForClientMessagesResult
{
public WaitForClientMessagesResult() {}
[DataMember]
WebClientMessage [] Messages;
}
这也没用。这里有两个问题。首先,JSON根对象有一个名为
WaitForClientMessagesResult
notMessages
的数组值属性,因此需要执行以下操作:
{
"WaitForClientMessagesResult": [
{
"__type": "KeepAliveMessage:#Data.WebGateway",
"MessageId": 1,
"Type": 0,
"PositionInQueue": -1
}
]
}
[KnownType(typeof(KeepAliveMessage))]
[DataContract]
public abstract class WebClientMessage
{
public WebClientMessage() { }
[DataMember]
public int MessageId { get; set; }
[DataMember]
public WebClientMessageType Type { get; set; }
}
[DataContract]
public class KeepAliveMessage : WebClientMessage
{
public KeepAliveMessage() { }
[DataMember]
public int PositionInQueue { get; set; }
}
[DataContract(Name = "WaitForClientMessagesResult", Namespace = "http://schemas.datacontract.org/2004/07/Data.WebGateway")]
public class WaitForClientMessagesResult
{
public WaitForClientMessagesResult() { }
[DataMember(Name = "WaitForClientMessagesResult")]
public WebClientMessage[] Messages { get; set; }
}
其次,您的JSON包含的格式为。您正在使用的JSON序列化程序JSON.NET。因此,您可能会考虑切换到<代码> DATACONTractJSONSerialStase。使用它,我可以按如下方式反序列化您的JSON:
public enum WebClientMessageType
{
KeepAliveMessage,
}
[KnownType(typeof(KeepAliveMessage))]
[DataContract(Name="WebClientMessage", Namespace="http://schemas.datacontract.org/2004/07/Data.WebGateway")]
public abstract class WebClientMessage
{
public WebClientMessage() { }
[DataMember]
public int MessageId { get; set; }
[DataMember]
public WebClientMessageType Type { get; set; }
}
[DataContract(Name = "KeepAliveMessage", Namespace = "http://schemas.datacontract.org/2004/07/Data.WebGateway")]
public class KeepAliveMessage : WebClientMessage
{
public KeepAliveMessage() { }
[DataMember]
public int PositionInQueue { get; set; }
}
public static class DataContractJsonSerializerHelper
{
public static string GetJson<T>(T obj, DataContractJsonSerializer serializer)
{
using (var memory = new MemoryStream())
{
serializer.WriteObject(memory, obj);
memory.Seek(0, SeekOrigin.Begin);
using (var reader = new StreamReader(memory))
{
return reader.ReadToEnd();
}
}
}
public static string GetJson<T>(T obj)
{
var serializer = new DataContractJsonSerializer(typeof(T));
return GetJson(obj, serializer);
}
public static T GetObject<T>(string json, DataContractJsonSerializer serializer)
{
using (var stream = GenerateStreamFromString(json))
{
var obj = serializer.ReadObject(stream);
return (T)obj;
}
}
public static T GetObject<T>(string json)
{
var serializer = new DataContractJsonSerializer(typeof(T));
return GetObject<T>(json, serializer);
}
private static MemoryStream GenerateStreamFromString(string value)
{
return new MemoryStream(Encoding.Unicode.GetBytes(value ?? ""));
}
}
公共枚举WebClient消息类型
{
请继续留言,
}
[KnownType(typeof(KeepAliveMessage))]
[DataContract(Name=“WebClient消息”,命名空间=”http://schemas.datacontract.org/2004/07/Data.WebGateway")]
公共抽象类WebClient消息
{
公共WebClient消息(){}
[数据成员]
public int MessageId{get;set;}
[数据成员]
公共WebClient消息类型{get;set;}
}
[DataContract(Name=“KeepAliveMessage”,命名空间=”http://schemas.datacontract.org/2004/07/Data.WebGateway")]
公共类KeepAliveMessage:WebClient消息
{
public KeepAliveMessage(){}
[数据成员]
public int PositionInQueue{get;set;}
}
公共静态类DataContractJsonSerializerHelper
{
公共静态字符串GetJson(T obj、DataContractJsonSerializer序列化程序)
{
使用(var memory=new MemoryStream())
{
serializer.WriteObject(内存,obj);
内存寻道(0,SeekOrigin.Begin);
使用(变量读取器=新的流读取器(内存))
{
返回reader.ReadToEnd();
}
}
}
公共静态字符串GetJson(T obj)
{
var serializer=newdatacontractjsonserializer(typeof(T));
返回GetJson(obj,序列化程序);
}
公共静态T GetObject(字符串json、DataContractJsonSerializer序列化程序)
{
使用(var-stream=GenerateStreamFromString(json))
{
var obj=serializer.ReadObject(流);
返回(T)obj;
}
}
公共静态T GetObject(字符串json)
{
var serializer=newdatacontractjsonserializer(typeof(T));
返回GetObject(json,序列化程序);
}
私有静态内存流生成器StreamFromString(字符串值)
{
返回新的MemoryStream(Encoding.Unicode.GetBytes(值??);
}
}
然后,为了测试:
public static void Test()
{
// Note there cannot be a space between the "{" and the "_type":
string json = @"{
""WaitForClientMessagesResult"": [
{""__type"": ""KeepAliveMessage:#Data.WebGateway"",
""MessageId"": 1,
""Type"": 0,
""PositionInQueue"": -1
}
]
}";
var result = DataContractJsonSerializerHelper.GetObject<WaitForClientMessagesResult>(json);
var newJson = DataContractJsonSerializerHelper.GetJson(result);
Debug.Assert(JToken.DeepEquals(JToken.Parse(json), JToken.Parse(newJson))); // No assert
}
公共静态无效测试()
{
//注意“{”和“_类型”之间不能有空格:
字符串json=@”{
“WaitForClientMessagesResult”“:[
{“uu类型”:“KeepAliveMessage:#Data.WebGateway”,
“MessageId”:1,
“”类型“”:0,
“”位置队列“”:-1
}
]
}";
var result=DataContractJsonSerializerHelper.GetObject(json);
var newJson=DataContractJsonSerializerHelper.GetJson(结果);
Assert(JToken.DeepEquals(JToken.Parse(json),JToken.Parse(newJson));//无Assert
}
如果你想坚持使用Json.NET,你需要编写自己的代码来解析
“\uuu type”
属性并反序列化正确的具体类型。以下是我如何解决这个问题的。这有点麻烦,但现在必须这样做:
Dictionary<string, object> deserialized = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
JArray messagesArray = deserialized["WaitForClientMessagesResult"] as JArray;
foreach (JObject gatewayMessage in messagesArray.Children<JObject>())
{
string messageJson = gatewayMessage.ToString();
WebClientMessageType messageType = GetMessageType(gatewayMessage);
WaitForClientMessagesResult msg = null;
switch (messageType)
{
case WebClientMessageType.KeepAlive:
msg = JsonConvert.DeserializeObject<KeepAliveMessage>(messageJson);
break;
default:
break;
}
}
字典反序列化=JsonConvert.DeserializeObject(json);
JArray messagesArray=反序列化为JArray的[“WaitForClientMessagesResult”];
foreach(messagesArray.Children()中的JObject网关消息)
{
字符串messageJson=gatewayMessage.ToString();
WebClientMessageType messageType=GetMessageType(网关消息);
WaitForClientMessagesResult msg=null;
开关(消息类型)
{
案例WebClientMessageType.KeepAlive:
msg=JsonConvert.DeserializeObject(messageJson);
打破
违约:
打破
}
}
我已经剥离了其他业务逻辑,只是发布了Json处理。如果有更好的方法,我将在稍后探讨
谢谢大家的帮助:)没有你的反馈,我无法到达这里
Matt向我们展示了如何声明
WaitForClientMessagesResult
。是否需要使用\uuu type
属性?如果这样,则会变得更复杂一点,\uu type字段来自webservice,我无法更改。它正在使用.NET序列化。“\uu type”
property是DataContractJsonSerializer
格式化多态类型信息的方式。Json.NET使用完全不同的格式