与空白WCF JSON反序列化问题 [英] WCF JSON Deserialization Issues with Whitespace

查看:176
本文介绍了与空白WCF JSON反序列化问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个接受的自定义DataContract参数作为一个JSON REST WCF服务,可以由超强型或子类型。当我通过包含额外的空白JSON,对象总是反序列化的超类型。当我从JSON去除所有的空白,对象deserializaes作为子类



下面是一个例子:



<预类=郎-CS prettyprint-覆盖> [DataContract]
[KnownType(typeof运算(子类))]
公共类父类
{
〔数据成员]
公共字符串消息{搞定;组; }
}

[DataContract]
公共类亚纲:父类
{
[数据成员]
公共字符串额外{搞定;组; }
}

[的ServiceContract]
公共接口IService1
{
[OperationContract的]
[WebInvoke]
无效的LogMessage(超类ARG);
}

公共类服务1:IService1
{
公共无效的LogMessage(父类ARG)
{
如果(arg是子类)
{
的Debug.WriteLine(子类);
}
,否则如果(arg是超类)
{
的Debug.WriteLine(父类);
}
}
}

如果我发送以下信息,该服务将打印父类

  POST HTTP://本地主机:5763 / Service1.svc /的LogMessage HTTP / 1.1 
的User-Agent:小提琴手
内容类型:文本/ JSON
主机:本地主机:5763
的Content-Length:86

{__type:子类:#WhitespaceTest,消息:信息,号外:额外}

我得到同样的结果,如果我漂亮打印的数据包,以及这样的JSON拆分为多行。但是,该服务将打印 SubClass中如果我脱光了空白如下:

  POST HTTP://本地主机:5763 / Service1.svc /的LogMessage HTTP / 1.1 
的User-Agent:小提琴手
内容类型:文本/ JSON
主机:本地主机:5763
的Content-Length:73

{__type:子类:#WhitespaceTest,消息:信息,号外:额外}

我已经调试 System.ServiceModel.OperationContext.Current.RequestContext.RequestMessage.ToString的输出() ,发现从JSON生成的XML是2包之间的不同:



<预类=郎咸平的XML prettyprint-覆盖> <! - 一包,反序列化向超 - >
<根型=对象>
< __类型type =字符串>亚纲:#WhitespaceTest< / __类型>
<消息类型=字符串>消息< /信息>
<额外的类型=字符串>及额外LT; /额外>
< /根>

<! - 二包,解串子类 - >
<根型=对象__type =子类:#WhitespaceTest>
<消息类型=字符串>消息< /信息>
<额外的类型=字符串>及额外LT; /额外>
< /根>



因此​​,它好像空白混淆了JSON解串器。有谁知道为什么会这样和我能做些什么呢?


解决方案

这是一个已知的问题,它被固定在4.5框架。不幸的是,你需要的本质,如果你想在目前的框架版本使用多态,从对象的前线地带的空格。做到这一点的方法之一是读/使用由 JsonReaderWriterFactory 创建一个读/写写JSON,因为这将去掉空格(或任何漂亮打印)围绕元素

 公共类StackOverflow_8661714 
{
[DataContract(NAME =超类,命名空间=WhitespaceTest )]
[KnownType(typeof运算(子类))]
公共类父类
{
[数据成员]
公共字符串消息{搞定;组; }
}

[DataContract(NAME =子类,命名空间=WhitespaceTest)]
公共类亚纲:父类
{
[数据成员]
公共字符串额外{搞定;组; }
}
公共静态无效测试()
{
串originalJson ={\__ type\:\子类:WhitespaceTest\\ Message\:\Message\,\Extra\:\Extra\};
字节[] = originalJsonBytes Encoding.UTF8.GetBytes(originalJson);
MemoryStream的writeStream =新的MemoryStream();
的XmlDictionaryWriter jsonWriter = JsonReaderWriterFactory.CreateJsonWriter(writeStream,Encoding.UTF8,FALSE);
XmlDictionaryReader jsonReader = JsonReaderWriterFactory.CreateJsonReader(originalJsonBytes,0,originalJsonBytes.Length,XmlDictionaryReaderQuotas.Max);
jsonWriter.WriteNode(jsonReader,真);
jsonWriter.Flush();
Console.WriteLine(Encoding.UTF8.GetString(writeStream.ToArray()));
writeStream.Position = 0;

DataContractJsonSerializer dcjs =新DataContractJsonSerializer(typeof运算(超类),新类型[] {typeof运算(子类)});
对象o = dcjs.ReadObject(writeStream);
Console.WriteLine(O);
}
}


I have a WCF REST service that accepts a custom DataContract argument as JSON which may either by the super-type or a sub-type. When I pass JSON containing extra whitespace, the object always deserializes as the super-type. When I strip all whitespace from the JSON, the object deserializaes as the sub-type.

Here is an example:

[DataContract]
[KnownType(typeof(SubClass))]
public class SuperClass
{
    [DataMember]
    public string Message { get; set; }
}

[DataContract]
public class SubClass : SuperClass
{
    [DataMember]
    public string Extra { get; set; }
}

[ServiceContract]
public interface IService1
{
    [OperationContract]
    [WebInvoke]
    void LogMessage(SuperClass arg);
}

public class Service1 : IService1
{
    public void LogMessage(SuperClass arg)
    {
        if (arg is SubClass)
        {
            Debug.WriteLine("SubClass");
        }
        else if (arg is SuperClass)
        {
            Debug.WriteLine("SuperClass");
        }
    }
}

If I send the following message, the service will print SuperClass:

POST http://localhost:5763/Service1.svc/LogMessage HTTP/1.1
User-Agent: Fiddler
Content-Type: text/json
Host: localhost:5763
Content-Length: 86

{    "__type":"SubClass:#WhitespaceTest",    "Message":"Message",    "Extra":"Extra" }

I get the same result if I "pretty print" the packet as well so that the JSOn is split over multiple lines. However, the service will print SubClass if I strip the whitespace as follows:

POST http://localhost:5763/Service1.svc/LogMessage HTTP/1.1
User-Agent: Fiddler
Content-Type: text/json
Host: localhost:5763
Content-Length: 73

{"__type":"SubClass:#WhitespaceTest","Message":"Message","Extra":"Extra"}

I've debugged the output of System.ServiceModel.OperationContext.Current.RequestContext.RequestMessage.ToString() and noticed that the XML generated from the JSON is different between the 2 packets:

<!-- First packet, deserializes to SuperClass -->
<root type="object">
    <__type type="string">SubClass:#WhitespaceTest</__type>
    <Message type="string">Message</Message>
    <Extra type="string">Extra</Extra>
</root>

<!-- Second packet, deserializes to SubClass -->
<root type="object" __type="SubClass:#WhitespaceTest">
    <Message type="string">Message</Message> 
    <Extra type="string">Extra</Extra> 
</root>

So, it seems as though the whitespace confuses the JSON deserializer. Does anyone know why this happens and what I can do about it?

解决方案

This is a known issue which was fixed in the 4.5 framework. Unfortunately you essentially need to strip the white spaces from the front of the object if you want to use polymorphism in the current framework version. One way to do that is to read / write the JSON using a reader / writer created by JsonReaderWriterFactory, as it will strip the white spaces (or any pretty printing) around the elements.

public class StackOverflow_8661714
{
    [DataContract(Name = "SuperClass", Namespace = "WhitespaceTest")]
    [KnownType(typeof(SubClass))]
    public class SuperClass
    {
        [DataMember]
        public string Message { get; set; }
    }

    [DataContract(Name = "SubClass", Namespace = "WhitespaceTest")]
    public class SubClass : SuperClass
    {
        [DataMember]
        public string Extra { get; set; }
    }
    public static void Test()
    {
        string originalJson = "{    \"__type\":\"SubClass:WhitespaceTest\",    \"Message\":\"Message\",    \"Extra\":\"Extra\" }";
        byte[] originalJsonBytes = Encoding.UTF8.GetBytes(originalJson);
        MemoryStream writeStream = new MemoryStream();
        XmlDictionaryWriter jsonWriter = JsonReaderWriterFactory.CreateJsonWriter(writeStream, Encoding.UTF8, false);
        XmlDictionaryReader jsonReader = JsonReaderWriterFactory.CreateJsonReader(originalJsonBytes, 0, originalJsonBytes.Length, XmlDictionaryReaderQuotas.Max);
        jsonWriter.WriteNode(jsonReader, true);
        jsonWriter.Flush();
        Console.WriteLine(Encoding.UTF8.GetString(writeStream.ToArray()));
        writeStream.Position = 0;

        DataContractJsonSerializer dcjs = new DataContractJsonSerializer(typeof(SuperClass), new Type[] { typeof(SubClass) });
        object o = dcjs.ReadObject(writeStream);
        Console.WriteLine(o);
    }
}

这篇关于与空白WCF JSON反序列化问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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