C# 客户端上的Json反序列化类结构

C# 客户端上的Json反序列化类结构,c#,json,deserialization,C#,Json,Deserialization,我无法在客户端端点上反序列化JSON数据。它接收的JSON数据如下: { "WaitForClientMessagesResult": [ { "__type": "KeepAliveMessage:#Data.WebGateway", "MessageId": 1, "Type": 0, "PositionInQueue": -1 } ] } [Kn

我无法在客户端端点上反序列化JSON数据。它接收的JSON数据如下:

{
    "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)
如果这些有效,则没有

我不知道如何在客户端构造类以使用Json反序列化器

编辑: 我的基类定义如下:

{
    "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
not
Messages
的数组值属性,因此需要执行以下操作:

{
    "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使用完全不同的格式