3

我有一个问题发生在我们的客户身上,但在使用相同的应用程序版本和数据时不会发生在任何开发人员身上。

DataContractJsonSerializer.ReadObject抛出此异常:

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

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

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

我最好的猜测是这是一个文本编码问题,因为 UTF-8 字节对0xC2,0x??最终会像Â转换为Windows 1252ISO 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 字符串中的引号(0xC2,0xA6在 UTF-8 中,因此可能是损坏字符的罪魁祸首)。

所以我们在 .Net 实例中有有效的 JSON string,我们使用 转换它UTF8.GetBytes,但是当DataContractJsonSerializer.ReadObject读取它时我们得到一个损坏。

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

4

1 回答 1

1

这是由于在 .Net 4.0 的补丁中修复的DataContractJsonSerializer.ReadObject(Stream)方法中的错误 - 开发人员有补丁,但我们的用户没有,这就是我们没有得到它的原因。

如果单个序列化对象中有大量非 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);
}

此处没有任何开发人员机器抛出异常,但我们客户的 PC 会抛出异常。

解决方法是使用缓冲的 JSON 阅读器而不是MemoryStream

using (var jsonReader = JsonReaderWriterFactory.CreateJsonReader(result, XmlDictionaryReaderQuotas.Max))
{
    var outputSerialiser = new DataContractJsonSerializer(typeof(string));
    string output = (string) outputSerialiser.ReadObject(jsonReader);
}
于 2014-05-29T14:06:15.387 回答