DataContractJsonSerializer.ReadObject иногда выдает: токен "ожидался, но найден"

У меня есть проблема, которая возникает у наших клиентов, но не возникает ни у кого из разработчиков при использовании той же версии приложения и данных.

DataContractJsonSerializer.ReadObject выдает это исключение:

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

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

Это исключение не возникает, когда кто-либо из разработчиков или я пытаемся воспроизвести его, но постоянно возникает в клиентских системах. Все используют Windows 7 64bit.

Насколько я понимаю, это проблема с кодировкой текста, поскольку пара байтов UTF-8 из 0xC2,0x?? в конечном итоге станет Â при преобразовании в 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 (это 0xC2,0xA6 в UTF-8, поэтому вероятный виновник поврежденного символа).

Итак, у нас есть действительный JSON в экземпляре .Net string, мы конвертируем его с помощью UTF8.GetBytes, но когда DataContractJsonSerializer.ReadObject читает его, мы получаем повреждение.

Любая идея, почему это происходит? Почему это происходит на одних машинах, а не на других?


person Keith    schedule 28.05.2014    source источник


Ответы (1)


Это из-за ошибки в методе DataContractJsonSerializer.ReadObject(Stream), исправленной в патче для .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);
}
person Keith    schedule 29.05.2014
comment
Исправление не решило проблему для меня! К счастью, в моем проекте разрешили использовать Newtonsoft. :-) - person James; 16.06.2016
comment
@james после других проблем (в основном из-за плохой реализации даты, которая зависит от eval), мы пошли тем же путем. - person Keith; 16.06.2016