DataContractJsonSerializer.ReadObject有时会抛出:令牌“是预期但发现'''

时间:2014-05-28 10:34:36

标签: .net json utf-8 datacontractjsonserializer

我的客户遇到了一个问题,但在使用相同的应用程序版本和数据时,任何开发人员都不会遇到此问题。

DataContractJsonSerializer.ReadObject抛出此异常:

  

Deserialising: There was an error deserializing the object of type {type}.

     

The token '"' was expected but found 'Â'.

当任何开发人员或我尝试重现它时,不会抛出此异常,但始终在客户端系统上发生。每个人都在使用Windows 7 64位。

我最好的猜测是,这是一个文本编码问题,因为0xC2,0x??的UTF-8字节对如果转换为 Windows 1252 将最终为Â ISO 8859-1

转换为UTF-8正在代码中完成:

string content = GetSerialised();
byte[] result = Encoding.UTF8.GetBytes(content);
using (var s = new MemoryStream(result))
{
    var outputSerialiser = new DataContractJsonSerializer(typeof(T), null, int.MaxValue, true, null, false);
    return (T) outputSerialiser.ReadObject(s);
}

显示content并显示错误消息,因此我们可以验证它是否是有效的JSON文本。它确实包含JSON字符串中引用的¦(UTF-8中的0xC2,0xA6,因此可能是损坏字符的罪魁祸首。)

因此,我们在.Net string实例中使用了有效的JSON,我们使用UTF8.GetBytes对其进行转换,但当DataContractJsonSerializer.ReadObject读取它时,我们会发现损坏。

知道为什么会这样吗?为什么它出现在某些机器而不是其他机器上?

1 个答案:

答案 0 :(得分:1)

这是due to a bug in the DataContractJsonSerializer.ReadObject(Stream) method已修复到.Net 4.0的补丁 - 开发人员有补丁但我们的用户没有,这就是为什么我们没有得到它。

如果单个序列化对象中有许多非ANSI字符,则会出现错误。

我写了一个简单的应用来检查问题:

// Create a JSON string with more non-ANSI characters than can be handled
char test = (char) 0x6cd5;
string content = "\"" + new string(test, 2048) + "\"";

// Use a MemoryStream
byte[] result = Encoding.UTF8.GetBytes(content);
using (var s = new MemoryStream(result))
{
    var outputSerialiser = new DataContractJsonSerializer(typeof(string));

    // This line will throw the exception
    string output = (string) outputSerialiser.ReadObject(s);
}

这些开发者机器都没有抛出异常,但是我们的客户'电脑可以。

修复方法是使用缓冲的JSON阅读器而不是MemoryStream

using (var jsonReader = JsonReaderWriterFactory.CreateJsonReader(result, XmlDictionaryReaderQuotas.Max))
{
    var outputSerialiser = new DataContractJsonSerializer(typeof(string));
    string output = (string) outputSerialiser.ReadObject(jsonReader);
}