Ошибка десериализации что это

Бывают ситуации, когда пользователь программы 1С сталкивается с появлением ошибки ⭐ «Ошибка десериализации контактной информации не указан ожидаемый тип». Возникает она в основном при переходе на новую редакцию программы или обновлении конфигурации и связана с некорректной конвертацией справочника «Виды контактной информации», а появляется при попытке занести данные

Бывают ситуации, когда пользователь программы 1С сталкивается с появлением ошибки – «Ошибка десериализации контактной информации не указан ожидаемый тип». Возникает она в основном при переходе на новую редакцию программы или обновлении конфигурации и связана с некорректной конвертацией справочника «Виды контактной информации», а появляется при попытке занести данные.

Данные «Контактная информация» задействованы в справочниках «Организация», «Подразделения организации», «Контрагенты», «Контактные лица». Их можно просмотреть, открыв раздел «Справочники», используя пункт меню «Все функций». Если этот раздел не доступен, включить его можно в разделе «Сервис» — «Параметры».

Рис.1 Контактная информация
Рис.1 Контактная информация
Рис.2 Контактная информация
Рис.2 Контактная информация

Пример заполнения «Контактной информации» в справочнике «Контрагенты».

Рис.3 «Контактная информация» в справочнике «Контрагенты»
Рис.3 «Контактная информация» в справочнике «Контрагенты»

Если мы откроем и посмотрим настройку элемента справочника «Контактная информация», например, «Юридический адрес», то мы увидим, что в поле «Тип» установлено значение «Адрес». Это верное значение, для данного вида информации.

Рис.4 Юридический адрес
Рис.4 Юридический адрес

Но, возможно, здесь некорректное отображение по каким-либо причинам, например, в процессе переноса данных из старой версии в новую могли быть перенесены лишние элементы. Их можно удалить. Также надо проверить остальные виды контактной информации, чтобы там не было пустых и неправильно заполненных полей. В случае обнаружения недочета, его также необходимо устранить.

Открыв любой вид контактной информации, мы видим, что в поле нет кнопки выбора, чтобы сменить (или установить в случае отсутствия) тип, но можно выйти из ситуации, используя копирование элемента и установку пометки на удаления неправильного элемента. В этом случае кнопка выбора типа информации активна.

Рис.5 Кнопка выбора типа информации активна
Рис.5 Кнопка выбора типа информации активна

После корректировки типа представления информации ошибка десериализации появляться не будет.

Еще одним способом устранения проблемы (более простым) является использование обработки по установке типа контактной информации «УстановкаТиповИВидовКИ». Ее можно найти в интернете, она написана сторонними разработчиками и для обычных форм, и для управляемых. С ее помощью можно изменить тип любого элемента справочника «Контактная информация».

Рис.6 УстановкаТиповИВидовКИ
Рис.6 УстановкаТиповИВидовКИ

Выбираем элемент, который необходимо исправить, задаем правильный тип и нажимаем кнопку «Установить тип».

Рис.7 Установить тип
Рис.7 Установить тип

С изменением типа представления контактной информации ошибка появляться не будет. При этом необходимо обратить внимание, на какой элемент программа «ругается» – это может быть не только адрес, но и, например, телефон, адрес электронной почты. Тогда действие производится с указанным элементом.

Содержание

  1. DeserializationError
  2. Description
  3. Values
  4. DeserializationError::Ok
  5. DeserializationError::EmptyInput
  6. DeserializationError::IncompleteInput
  7. DeserializationError::InvalidInput
  8. DeserializationError::NoMemory
  9. DeserializationError::NotSupported ⚠️ removed
  10. DeserializationError::TooDeep
  11. Methods
  12. How to know where deserialization stopped?
  13. Serialization Error Handling
  14. Как не наступить на грабли, работая с сериализацией
  15. Для кого статья?
  16. Реализуя ISerializable, не забудьте про конструктор сериализации
  17. Обращайте внимание на модификатор доступа конструктора сериализации
  18. Конструктор сериализации в незапечатанном классе имеет модификатор доступа ‘private’
  19. Не объявляйте конструктор сериализации с модификаторами ‘public’ или ‘internal’
  20. Реализуйте виртуальный метод GetObjectData в незапечатанных классах
  21. Все сериализуемые члены должны иметь сериализуемый тип
  22. Не забывайте про атрибут [Serializable] при реализации интерфейса ISerializable
  23. Убедитесь, что в методе GetObjectData сериализуются все необходимые члены типа
  24. Обобщение
  25. Заключение
  26. Дополнительная информация

DeserializationError

Description

Values

A DeserializationError is an enumerated type that can contain one of the following values:

DeserializationError::Ok

The deserialization succeeded. Cool!

DeserializationError::EmptyInput

The input was empty or contained only spaces or comments. Possible reasons:

  • a timeout occurred when reading from a stream (see How to change the timeout)
  • the server returned a redirection code (like 301 Moved Permanently or 302 Found)
  • the certificate validation failed (try WiFiClientSecure::setInsecure() )
  • the stream is not connected
  • the file was not found
  • the file is empty
  • the file was opened in the wrong mode

EmptyInput was added in ArduinoJson 6.17.0

DeserializationError::IncompleteInput

The end of the input is missing. Possible reasons:

  • a buffer was too small to contains the input
  • a timeout occurred when reading from a stream (see How to change the timeout)

Before ArduinoJson 6.17.0, IncompleteInput could also mean “empty input.”

DeserializationError::InvalidInput

The input is not recognized. Possible reasons:

  • the input is simply invalid
  • the input contains a comment, but support is disabled 🆕
  • the input is valid but is preceded by something else (see below)
  • you called deserializeJson() twice in zero-copy mode

If this error occurs on an HTTP response, ensure your program:

  1. skips the HTTP headers
  2. uses HTTP version 1.0 or handles chunked transfer encoding

This error also occurs if the input document starts with a byte order mark (BOM). This problem is hard to diagnose because the BOM is an invisible character, so you can’t see it in the Serial Monitor and in most text editors. The easiest way to check if the BOM is present is to read the first byte of the input (for example, you can do Serial.print((char)client.read()) ). The first character should be a < or a [ ; if you see something else, then it’s surely the BOM. If that’s your case, you must skip the first two bytes before calling deserializeJson() , like so:

Of course, the best solution is still to remove the BOM from the server side.

DeserializationError::NoMemory

The JsonDocument is too small; you need to increase its capacity.

When using a DynamicJsonDocument , it can also mean that the allocation of the memory pool failed.
You can check whether the allocation succeeded by looking at JsonDocument::capacity() .

DeserializationError::NotSupported ⚠️ removed

The document included features not supported by the parser. Possible reasons:

  • the JSON input contains a Unicode escape sequence (like u0032 ), but support is disabled
  • the MessagePack input contains a binary value
  • the MessagePack input contains an object key that is not a string

NotSupported was removed in ArduinoJson 6.18.0. Instead, deserializeJson() ignores the Unicode escape sequences when ARDUINOJSON_DECODE_UNICODE is 0 (the default is 1 since 6.16), and deserializeMsgPack() replaces unsupported values with nulls.

DeserializationError::TooDeep

The nesting limit was reached; you need to increase its value. See deserializeJson() , or ARDUINOJSON_DEFAULT_NESTING_LIMIT for details.

Methods

How to know where deserialization stopped?

When you pass a Stream to deserializeJson() , it consumes the input but doesn’t print anything to the serial, which makes troubleshooting difficult.

If you want to see what deserializeJson() consumed, use ReadLoggingStream from the StreamUtils library (see example below). Because ArduinoJson stops reading as soon as it sees an error, you can see what caused the error by checking the last consumed character.

Источник

Serialization Error Handling

Json.NET supports error handling during serialization and deserialization. Error handling lets you catch an error and choose whether to handle it and continue with serialization or let the error bubble up and be thrown in your application.

Error handling is defined through two methods: the Error event on JsonSerializer and the OnErrorAttribute.

The Error event is an event handler found on JsonSerializer. The error event is raised whenever an exception is thrown while serializing or deserializing JSON. Like all settings found on JsonSerializer, it can also be set on JsonSerializerSettings and passed to the serialization methods on JsonConvert.

In this example we are deserializing a JSON array to a collection of DateTimes. On the JsonSerializerSettings a handler has been assigned to the Error event which will log the error message and mark the error as handled.

The result of deserializing the JSON is three successfully deserialized dates and three error messages: one for the badly formatted string («I am not a date and will error!»), one for the nested JSON array, and one for the null value since the list doesn’t allow nullable DateTimes. The event handler has logged these messages and Json.NET has continued on deserializing the JSON because the errors were marked as handled.

One thing to note with error handling in Json.NET is that an unhandled error will bubble up and raise the event on each of its parents. For example an unhandled error when serializing a collection of objects will be raised twice, once against the object and then again on the collection. This will let you handle an error either where it occurred or on one of its parents.

If you aren’t immediately handling an error and only want to perform an action against it once, then you can check to see whether the ErrorEventArgs’s CurrentObject is equal to the OriginalObject. OriginalObject is the object that threw the error and CurrentObject is the object that the event is being raised against. They will only equal the first time the event is raised against the OriginalObject.

Источник

Как не наступить на грабли, работая с сериализацией

Несмотря на то, что использовать механизм сериализации при программировании на C# достаточно просто и удобно, есть моменты, которые стоит учитывать. О том, на какие грабли можно наступить, работая с сериализацией, о примерах кода, в котором эти грабли припрятаны, а также о том, как PVS-Studio поможет вам избежать шишек на лбу, и будет эта статья.

Для кого статья?

Данная статья будет особенно полезна разработчикам, только начинающим знакомиться с механизмом сериализации. Более опытные программисты также могут почерпнуть для себя что-то интересное, или просто убедиться, что даже профессионалы порой допускают ошибки.

Тем не менее, подразумевается, что читатель уже знаком с механизмом сериализации.

При чём тут PVS-Studio? В релизе 6.05 были добавлены 6 диагностических правил, обнаруживающих подозрительный код, связанный с использованием механизма сериализации. Эти диагностики в основном ищут проблемные места, связанные с атрибутом [Serializable] или реализацией интерфейса ISerializable.

Стоит понимать, что описанные в статье утверждения актуальны для некоторых сериализаторов, например — BinaryFormatter и SoapFormatter, а для других, например, собственноручно написанного сериализатора, поведение может отличаться. Например, отсутствие атрибута [Serializable] у класса может не помешать проводить его сериализацию и десериализацию собственным сериализатором.

Кстати, если вы работаете с сериализацией, советую загрузить пробную версию анализатора и проверить свой код на наличие подозрительных мест.

Реализуя ISerializable, не забудьте про конструктор сериализации

Реализация типом интерфейса ISerializable позволяет управлять сериализацией, выбирая, какие члены нужно сериализовать, какие — нет, какие значение нужно записывать при сериализации членов и т.п.

Интерфейс ISerializable содержит объявление одного метода — GetObjectData, который будет вызван при сериализации объекта. Но в паре с этим методом обязательно должен быть реализован конструктор, который будет вызываться при десериализации объекта. Так как интерфейс не может обязать вас реализовать в своем типе какой-то конструктор, эта задача ложится на плечи программиста, занимающегося реализацией сериализуемого типа. Конструктор сериализации имеет следующую сигнатуру:

Без наличия данного конструктора сериализация объекта пройдёт успешно (при условии корректной реализации метода GetObjectData), но восстановить (десериализовать) его не удастся — будет сгенерировано исключение типа SerializationException.

Посмотрим на пример подобного кода из проекта Glimpse:

Предупреждение PVS-Studio: V3094 Possible exception when deserializing. The SerializableTestObject(SerializationInfo, StreamingContext) constructor is missing. Glimpse.Test.AspNet SessionModelConverterShould.cs 111

Сериализация экземпляра данного класса пройдёт успешно, а вот при десериализации возникнет исключение, так как нет соответствующего конструктора. Скорее всего, это не ошибка (исходя из названия класса и файла), но в качестве иллюстрации описанной ситуации — то, что нужно.

Конструктор сериализации для данного класса мог бы выглядеть так:

Обращайте внимание на модификатор доступа конструктора сериализации

При разработке типа, реализующего интерфейс ISerializable, важно правильно определить модификатор доступа для конструктора сериализации. Здесь возможны несколько случаев:

  • конструктор сериализации объявлен с модификатором private в незапечатанном классе;
  • конструктор сериализации объявлен с модификатором доступа public или internal;
  • конструктор сериализации объявлен с модификатором protected в запечатанном классе.

Наибольший интерес представляет первый из приведённых выше вариантов, так как он таит в себе наибольшую опасность. Кратко остановимся и на втором пункте, а третий рассматривать не будем — объявить член с модификатором protected в структуре не даст компилятор (ошибка компиляции), если такой член объявляется в запечатанном классе — компилятор выдаст предупреждение.

Конструктор сериализации в незапечатанном классе имеет модификатор доступа ‘private’

Это наиболее опасный случай из ситуаций неправильного применения модификаторов доступа к конструкторам сериализации. Если тип является незапечатанным, подразумевается, что у него могут быть наследники. Однако если конструктор сериализации имеет модификатор доступа private, он не сможет быть вызван из дочернего класса.

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

  • не факт, что в базовом классе была предусмотрена тривиальная десериализация членов;
  • разработчик дочернего класса может забыть десереализовать какой-либо член базового класса;
  • при всём желании, десериализовать приватные члены базового класса не удастся.

Поэтому, разрабатывая незапечатанный сериализуемый класс, обращайте внимание на то, какой модификатор доступа имеет конструктор сериализации.

При анализе проектов удалось найти несколько таких, в которых описанное выше правило не соблюдалось.

Предупреждение PVS-Studio: V3103 A private Ctor(SerializationInfo, StreamingContext) constructor in unsealed type will not be accessible when deserializing derived types. NHibernate ConnectionManager.cs 276

Предупреждение PVS-Studio: V3103 A private TestDiagnostic(SerializationInfo, StreamingContext) constructor in unsealed type will not be accessible when deserializing derived types. DiagnosticAnalyzerTests.cs 100

В обоих примерах, приведённых выше, у конструктора сериализации следовало установить модификатор доступа protected, чтобы дочерние классы могли вызвать его при десериализации.

Не объявляйте конструктор сериализации с модификаторами ‘public’ или ‘internal’

Это совет хорошего стиля программирования. Объявление конструктора сериализации с модификатором public или internal не приведёт к ошибке, но смысла в этом нет — данный конструктор не должен вызываться извне, а сериализатору без разницы, какой модификатор доступа имеет конструктор.

При проверке open source проектов встретились несколько таких, в которых это правило не соблюдалось.

Предупреждение PVS-Studio: V3103 The Ctor(SerializationInfo, StreamingContext) constructor should be used for deserialization. Making it internal is not recommended. Consider making it private. Microsoft.Build.Tasks SystemState.cs 218

Предупреждение PVS-Studio: V3103 The Ctor(SerializationInfo, StreamingContext) constructor should be used for deserialization. Making it internal is not recommended. Consider making it private. Microsoft.Build.Tasks SystemState.cs 139

В обоих случаях для конструктора сериализации следовало установить модификатор доступа private, так оба класса, приведённых выше, являются запечатанными.

Предупреждение PVS-Studio: V3103 The Ctor(SerializationInfo, StreamingContext) constructor should be used for deserialization. Making it internal is not recommended. Consider making it protected. NHibernate StatefulPersistenceContext.cs 1478

Предупреждение PVS-Studio: V3103 The Ctor(SerializationInfo, StreamingContext) constructor should be used for deserialization. Making it public is not recommended. Consider making it protected. NHibernate Configuration.cs 84

Ввиду того, что оба класса являются незапечатанными, для конструкторов сериализации следовало установить модификатор доступа protected.

Реализуйте виртуальный метод GetObjectData в незапечатанных классах

Правило простое — если вы разрабатываете незапечатанный класс, реализующий интерфейс ISerializable, объявите метод GetObjectData с модификатором virtual. Это позволит дочерним классам корректно производить сериализацию объекта при использовании полиморфизма.

Чтобы лучше понять суть проблемы, предлагаю рассмотреть несколько примеров.

Допустим, у нас есть следующие объявления родительского и дочернего классов.

Предположим, что имеется метод сериализации и десереализации объекта следующего вида:

В таком случае сериализация выполнится неправильно из-за того, что будет вызван метод GetObjectData не дочернего, а родительского класса. Следовательно, члены дочернего класса не будут сериализованы. Если при десериализации из объекта типа SerializationInfo будут извлекаться значения членов, добавляемых в методе GetObjectData дочернего класса, будет сгенерировано исключение, так как объект типа SerializationInfo не будет содержать запрашиваемых ключей.

Для исправления ошибки в родительском классе к методу GetObjectData необходимо добавить модификатор virtual, в производном — override.

Если в родительском классе присутствует только явная реализация интерфейса ISerializable, добавить к ней модификатор virtual вы не сможете. Однако оставив всё, как есть, вы рискуете усложнить жизнь разработчикам дочерних классов.

Рассмотрим пример реализации родительского и дочернего классов:

В таком случае из дочернего класса будет невозможно обратиться к методу GetObjectData родительского класса. И если в базовом методе сериализуются приватные члены, обратиться к ним из дочернего класса также не удастся, а значит и не удастся провести корректную сериализацию. Для исправления ошибки помимо явной реализации в базовый класс необходимо добавить неявную реализацию виртуального метода GetObjectData. Тогда исправленный код может выглядеть так:

Или же, если не подразумевается наследование данного класса, следует сделать его запечатанным, добавив к объявлению класса модификатор sealed.

Предупреждение PVS-Studio: V3104 ‘GetObjectData’ implementation in unsealed type ‘TestDiagnostic’ is not virtual, incorrect serialization of derived type is possible. CSharpCompilerSemanticTest DiagnosticAnalyzerTests.cs 112

Класс TestDiagnostic является незапечатанным (хоть и приватным, так что унаследоваться от него в рамках того же класса возможно), но при этом он имеет только явную реализацию интерфейса ISerializable, в которой, ко всему прочему, сериализуются приватные члены. Это означает одно — разработчик дочернего класса никаким образом не сможет сериализовать необходимые члены: метод GetObjectData будет ему недоступен, а обратиться к членам напрямую не позволит модификатор доступа.

Правильнее было бы вынести весь код сериализации, приведённый выше, в виртуальный метод GetObjectData, на который сослаться из явной реализации интерфейса:

Все сериализуемые члены должны иметь сериализуемый тип

Это условие является обязательным для корректной сериализации объекта вне зависимости от того, происходит ли автоматическая сериализация (когда тип декорирован атрибутом [Serializable] и при этом не реализует интерфейс ISerializable) или сериализация осуществляется вручную (реализован ISerializable).

В противном случае, если при сериализации встретится член, не декорированный атрибутом [Serializable], будет сгенерировано исключение типа SerializationException.

Если требуется сериализовать объект без учёта членов, имеющих несереализуемый тип, возможны несколько подходов:

  • сделайте несериализуемый тип сериализуемым;
  • если происходит автоматическая сериализация, декорируйте поля, которые не нужно сериализовать, атрибутом [NonSerialized];
  • если происходит ручная сериализация, просто игнорируйте те члены, которые вам не нужны.

Стоит обратить внимание на тот факт, что атрибут [NonSerialized] применим только к полям. Таким образом, вы не сможете запретить сериализацию свойства, но, если оно будет иметь несериализуемый тип — получите исключение. Например, при попытке сериализации класса SerializedClass, определение которого приведено ниже:

Обойти эту ситуацию можно, реализовав свойство через поле, декорированное атрибутом [NonSerialized]:

Подобные ошибки, когда сериализуемый тип имеет члены несереализуемых типов, не декорированные атрибутом [NonSerialized], обнаруживает диагностическое правило V3097 статического анализатора кода PVS-Studio.

Напоминаю, что данное предупреждение не обязательно свидетельствует о наличии ошибки — всё зависит от используемого сериализатора.

Рассмотрим несколько примеров кода, в которых описанное условие было нарушено.

Предупреждение PVS-Studio: V3097 Possible exception: the ‘AkismetSpamService’ type marked by [Serializable] contains non-serializable members not marked by [NonSerialized]. Subtext.Framework AkismetSpamService.cs 31

Тип BlogUrlHelper поля _urlHelper не является сериализуемым, поэтому при попытке сериализации экземпляра класса AkismetSpamService некоторыми сериализаторами, будет сгенерировано исключение типа SerializationException. Решать проблему нужно, отталкиваясь от ситуации. Если используются сериализаторы типа BinaryFormatter или SoapFormatter — необходимо либо декорировать поле атрибутом [NonSerialized], либо декорировать атрибутом [Serializable] тип BlogUrlHepler. Если используются другие сериализаторы, не требующие наличия атрибута [Serializable] у сериализуемых полей, можно не забивать голову.

Предупреждение PVS-Studio: V3097 Possible exception: the ‘ResponsibleLegalPerson’ type marked by [Serializable] contains non-serializable members not marked by [NonSerialized]. NHibernate.Test ResponsibleLegalPerson.cs 9

Ситуация аналогична описанной выше — или пан, или пропал. Всё зависит от используемого сериализатора.

Не забывайте про атрибут [Serializable] при реализации интерфейса ISerializable

Данный совет относится скорее к тем, кто только начинает работать с сериализацией. Управляя сериализацией вручную, посредством реализации интерфейса ISerializable, легко забыть декорировать тип атрибутом [Serializable], что потенциально приводит к генерации исключения типа SerializationException. Такие сериализаторы, как BinaryFormatter, требуют наличия данного атрибута.

Интересные примеры данной ошибки встретились в проекте SharpDevelop.

Предупреждение PVS-Studio: V3096 Possible exception when serializing ‘SearchPatternException’ type. [Serializable] attribute is missing. ICSharpCode.AvalonEdit ISearchStrategy.cs 80

Предупреждение PVS-Studio: V3096 Possible exception when serializing ‘DecompilerException’ type. [Serializable] attribute is missing. ICSharpCode.Decompiler DecompilerException.cs 28

Для передачи объекта исключения между доменами приложений происходит его сериализация и десериализация. Соответственно, собственные типы исключений должны быть сериализуемыми. В приведённых выше примерах типы SearchPatternException и DecompilerException наследуются от Exception и реализуют конструкторы сериализации, но при этом не декорированы атрибутом [Serializable], а значит, что при попытке сериализации объектов данных типов (например, для передачи между доменами) будет сгенерировано исключение типа SerializationException. Таким образом, например, генерируя исключение в другом домене приложений, в текущем вы перехватите не сгенерированное исключение, а SerializationException.

Убедитесь, что в методе GetObjectData сериализуются все необходимые члены типа

Реализуя интерфейс ISerializable и определяя метод GetObjectData, вы берёте на себя ответственность за то, какие члены типа будут сериализованы и какие значения в них будут записаны. В этом случае для разработчиков открывается большой простор в управлении сериализацией: в качестве сериализуемого значения, ассоциированного с членом (а если быть более честным — с любой строкой) вы можете записать действительное значение сериализованного объекта, результат работы какого-либо метода, константное или литеральное значение — всё, что захотите.

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

Для диагностирования таких ситуаций в статическом анализаторе кода PVS-Studio предусмотрено диагностическое правило V3099. Предлагаю ознакомиться с некоторыми примерами кода, обнаруженных данным правилом.

Предупреждение PVS-Studio: V3099 Not all the members of ‘XshdColor’ type are serialized inside ‘GetObjectData’ method: LineNumber, ColumnNumber. ICSharpCode.AvalonEdit XshdColor.cs 101

В этом коде нет проблем, описанных ранее, таких как неправильные модификаторы доступа у конструктора сериализации, отсутствие атрибута [Serializable] или модификатора virtual у метода GetObjectData.
Увы, ошибка здесь всё равно есть. В методе GetObjectData не учитываются свойства базового класса, а значит, при сериализации часть данных будет потеряна. В итоге, при десериализации будет восстановлен объект с другим состоянием.

В данном случае решением проблемы будет ручное добавление необходимых значений, например, таким образом:

Если бы базовый класс также реализовывал интерфейс ISerializable, решение было бы более элегантным — вызовом в производном методе GetObjectData базового.

Предупреждение PVS-Studio: V3099 Not all the members of ‘SessionImpl’ type are serialized inside ‘GetObjectData’ method: fetchProfile. NHibernate SessionImpl.cs 141

На этот раз забыли сериализовать поле текущего класса (fetchProfile). Как видно из определения, оно не декорировано атрибутом [NonSerialized] (в отличии от других полей, не сериализуемых в методе GetObjectData).

В данном проекте нашлось ещё два подобных места:

  • V3099 Not all the members of ‘Configuration’ type are serialized inside ‘GetObjectData’ method: currentDocumentName, preMappingBuildProcessed. NHibernate Configuration.cs 127
  • V3099 Not all the members of ‘ConnectionManager’ type are serialized inside ‘GetObjectData’ method: flushingFromDtcTransaction. NHibernate ConnectionManager.cs 290

С подобными ошибками связана интересная особенность — они либо приводят к генерации исключения, либо к трудноуловимым логическим ошибкам.

Исключение будет сгенерировано в том случае, если в конструкторе сериализации попытаются получить значение того поля, которое не было добавлено (обратятся по отсутствующему ключу). Если же про член забыли совсем (и в методе GetObjectData, и в конструкторе сериализации), будет происходить порча состояния объекта.

Обобщение

Заключение

Надеюсь, вы узнали что-то новое из статьи и стали большим экспертом в вопросах сериализации. Придерживаясь приведённых выше советов и правил, вы сможете тратить меньше времени на отладку, облегчить жизнь себе и другим разработчикам, работающим с вашими классами. А анализатор PVS-Studio ещё больше облегчит жизнь, позволяя выявлять подобные ошибки сразу после их появления.

Дополнительная информация

  • V3094. Possible exception when deserializing type. The Ctor(SerializationInfo, StreamingContext) constructor is missing
  • V3096. Possible exception when serializing type. [Serializable] attribute is missing
  • V3097. Possible exception: type marked by [Serializable] contains non-serializable members not marked by [NonSerialized]
  • V3099. Not all the members of type are serialized inside ‘GetObjectData’ method
  • V3103. A private Ctor(SerializationInfo, StreamingContext) constructor in unsealed type will not be accessible when deserializing derived types
  • V3104. ‘GetObjectData’ implementation in unsealed type is not virtual, incorrect serialization of derived type is possible
  • MSDN. Serialization in the .NET Framework
  • MSDN. Custom Serialization

Если хотите поделиться этой статьей с англоязычной аудиторией, то прошу использовать ссылку на перевод: Sergey Vasiliev. How to not shoot yourself in the foot when working with serialization.

Источник

MakcPletnev

41 / 37 / 9

Регистрация: 01.02.2014

Сообщений: 825

1

Ошибка десериализации объекта

05.04.2016, 00:24. Показов 5789. Ответов 9

Метки нет (Все метки)


Ошибка десериализации объекта типа RespGroup1. Символы с шестнадцатеричными значениями 0xFFFE и 0xFFFF являются недопустимыми

В общем, не может дисериализировать такой вот JSON (Именно этот пример, плейлист большинства дисериализирует без проблем, 1 раз такая проблема):

JSON
1
http://rghost.ru/private/6f7ljsrHg/3a189b713a9234a1c8060046ce5eb779 - на форум не влезло...

Код:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
[DataContract]
        public class RespGroup1
        {
            [DataMember(Name = "response")]
            public RespGroup2[] response { get; set; }
        }
        [DataContract]
        public class RespGroup2
        {
            [DataMember(Name = "count")]
            public string count { get; set; }
            [DataMember(Name = "items")]
            public Person[] items { get; set; }
        }
        [DataContract]
        public class Person
        {
            /*[DataMember(Name = "id")]
            public string id { get; set; }*/
 
            [DataMember(Name = "owner_id")]
            public string owner_id { get; set; }
            [DataMember(Name = "artist")]
            public string artist { get; set; }
            [DataMember(Name = "title")]
            public string title { get; set; }
 
            /*[DataMember(Name = "duration")]
            public string duration { get; set; }
            [DataMember(Name = "date")]
            public string date { get; set; }
            [DataMember(Name = "url")]
            public string url { get; set; }
            [DataMember(Name = "lyrics_id")]
            public string lyrics_id { get; set; }
            [DataMember(Name = "genre_id")]
            public string genre_id { get; set; }*/
        }
 
DataContractJsonSerializer json = new DataContractJsonSerializer(typeof(RespGroup1));
RespGroup1 person = (RespGroup1)json.ReadObject(new System.IO.MemoryStream(Encoding.Unicode.GetBytes(html)));

Помогите пожалуйста, добрые люди)

Добавлено через 13 секунд
Кому не сложно, подскажите…

Добавлено через 9 минут
Ev_Hyper, была бы очень кстати твоя помощь сейчас)

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь



0



Jason

525 / 487 / 98

Регистрация: 25.12.2011

Сообщений: 1,176

05.04.2016, 00:37

2

Просили — помогаю . Да вроде ничего сложного, Items — будет массив классов:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
        static void Main(string[] args)
        {
            DataContractJsonSerializer json = new DataContractJsonSerializer(typeof(Music));
            string fileContent = System.IO.File.ReadAllText(@"E:1.txt");
            Music music = (Music)json.ReadObject(new System.IO.MemoryStream(Encoding.UTF8.GetBytes(fileContent)));
            Console.WriteLine(music.items[1].artist);
            Console.ReadLine();
        }
 
        [DataContract]
        public class Music
        {
            [DataMember(Name = "count")]
            public string count { get; set; }
            [DataMember(Name = "items")]
            public Item[] items { get; set; }
 
            [DataContract]
            public class Item
            {
                [DataMember(Name = "id")]
                public string id { get; set; }
                [DataMember(Name = "owner_id")]
                public string owner_id { get; set; }
                [DataMember(Name = "artist")]
                public string artist { get; set; }
                [DataMember(Name = "title")]
                public string title { get; set; }
                [DataMember(Name = "duration")]
                public string duration { get; set; }
                [DataMember(Name = "date")]
                public string date { get; set; }
                [DataMember(Name = "url")]
                public string url { get; set; }
                [DataMember(Name = "lyrics_id")]
                public string lyrics_id { get; set; }
                [DataMember(Name = "genre")]
                public string genre { get; set; }
            }
        }

P.S. Только я удалил — {«response»:[ в начале и ]} в конце (для удобства).



0



41 / 37 / 9

Регистрация: 01.02.2014

Сообщений: 825

05.04.2016, 00:44

 [ТС]

3

Jason, попробуй это: https://yadi.sk/d/YG60-YYiqjhe9
Вот тут точно выбьет ошибку… Только что выковырнул кусок

Добавлено через 4 минуты
p.sы, там несколько блоков



0



525 / 487 / 98

Регистрация: 25.12.2011

Сообщений: 1,176

05.04.2016, 00:45

4

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



0



41 / 37 / 9

Регистрация: 01.02.2014

Сообщений: 825

05.04.2016, 00:46

 [ТС]

5

Jason, это тот же самый json , с описанием из шапки. Фишка в том, что выдает ошибку
«Символы с шестнадцатеричными значениями 0xFFFE и 0xFFFF являются недопустимыми», надо решить вопрос именно с ней…



0



Jason

525 / 487 / 98

Регистрация: 25.12.2011

Сообщений: 1,176

05.04.2016, 01:59

6

Вот так нужно было урезать структуру:

JSON
1
{"response":[{"count":1,"items":[{"id":456239020,"owner_id":35541739,"artist":"Response 1 - 1","title":"Du bist nicht allein","duration":241,"date":1459553197,"url":"http://cs4505.vk.me/u690598/audios/f1f28c909424.mp3?extra=fSUfByfOF6k73qvvAYQ6YdFm0hz-srnBbJtn1VsuTJQTMkm0O-Sw1HNGmM17MQoXoEpuNVSnGlRWpSFwxVH4OYJGY7SSGX6iZFFzTPFIdYoHK77MCKZFLm-AVxt6CX0SvMAoYRbvHDwQ","genre_id":18}]},{"count":2,"items":[{"id":456239020,"owner_id":35541739,"artist":"Response 2 - 1","title":"Du bist nicht allein","duration":241,"date":1459553197,"url":"http://cs4505.vk.me/u690598/audios/f1f28c909424.mp3?extra=fSUfByfOF6k73qvvAYQ6YdFm0hz-srnBbJtn1VsuTJQTMkm0O-Sw1HNGmM17MQoXoEpuNVSnGlRWpSFwxVH4OYJGY7SSGX6iZFFzTPFIdYoHK77MCKZFLm-AVxt6CX0SvMAoYRbvHDwQ","genre_id":18},{"id":456239020,"owner_id":35541739,"artist":"Response 2 - 2","title":"Du bist nicht allein","duration":241,"date":1459553197,"url":"http://cs4505.vk.me/u690598/audios/f1f28c909424.mp3?extra=fSUfByfOF6k73qvvAYQ6YdFm0hz-srnBbJtn1VsuTJQTMkm0O-Sw1HNGmM17MQoXoEpuNVSnGlRWpSFwxVH4OYJGY7SSGX6iZFFzTPFIdYoHK77MCKZFLm-AVxt6CX0SvMAoYRbvHDwQ","genre_id":18}]}]}

Так, а теперь код:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
        static void Main(string[] args)
        {
            DataContractJsonSerializer json = new DataContractJsonSerializer(typeof(Music));
            string fileContent = System.IO.File.ReadAllText(@"E:1.txt");
            Music music = (Music)json.ReadObject(new System.IO.MemoryStream(Encoding.UTF8.GetBytes(fileContent)));
            Console.WriteLine(music.response[0].items[0].artist);
            Console.WriteLine(music.response[1].items[1].artist);
            Console.ReadLine();
        }
 
        [DataContract]
        public class Music
        {
 
            [DataMember(Name = "response")]
            public Response[] response { get; set; }
 
            [DataContract]
            public class Response
            {
                [DataMember(Name = "count")]
                public string count { get; set; }
                [DataMember(Name = "items")]
                public Item[] items { get; set; }
 
                [DataContract]
                public class Item
                {
                    [DataMember(Name = "id")]
                    public string id { get; set; }
                    [DataMember(Name = "owner_id")]
                    public string owner_id { get; set; }
                    [DataMember(Name = "artist")]
                    public string artist { get; set; }
                    [DataMember(Name = "title")]
                    public string title { get; set; }
                    [DataMember(Name = "duration")]
                    public string duration { get; set; }
                    [DataMember(Name = "date")]
                    public string date { get; set; }
                    [DataMember(Name = "url")]
                    public string url { get; set; }
                    [DataMember(Name = "lyrics_id")]
                    public string lyrics_id { get; set; }
                    [DataMember(Name = "genre")]
                    public string genre { get; set; }
                }
            }
        }

P.S.

Цитата
Сообщение от MakcPletnev
Посмотреть сообщение

Символы с шестнадцатеричными значениями 0xFFFE и 0xFFFF являются недопустимыми», надо решить вопрос именно с ней…

А на счет этого, не нужно файлы сохранять в формате Юникод и т.п. Сохраните файл в ANSI и проверяем…

Либо пробовать что-то вроде этого:

C#
1
2
3
4
5
6
7
8
9
10
11
        static void Main(string[] args)
        {
            DataContractJsonSerializer json = new DataContractJsonSerializer(typeof(Music));
            string fileContent = System.IO.File.ReadAllText(@"E:1.txt");
            byte[] b = Encoding.Unicode.GetBytes(fileContent);
            b = Encoding.Convert(Encoding.Unicode, Encoding.ASCII, b);
            Music music = (Music)json.ReadObject(new System.IO.MemoryStream(b));
            Console.WriteLine(music.response[0].items[0].artist);
            Console.WriteLine(music.response[1].items[1].artist);
            Console.ReadLine();
        }



0



41 / 37 / 9

Регистрация: 01.02.2014

Сообщений: 825

06.04.2016, 21:04

 [ТС]

7

Jason, из-за этого не поддерживается кириллица, я пробовал уже
Есть еще варианты?

Добавлено через 1 минуту
русские символы отображаются в виде ‘?’



0



975 / 870 / 350

Регистрация: 26.04.2012

Сообщений: 2,647

07.04.2016, 02:36

8

Я большой JSON обычно не десериализую, а использую при при помощи библиотеки Newtonsoft.Json и тамошнего класса JToken.



0



41 / 37 / 9

Регистрация: 01.02.2014

Сообщений: 825

26.07.2016, 11:06

 [ТС]

9

EvilFromHell, может расскажете как?



0



Master of Orion

Эксперт .NET

6094 / 4950 / 905

Регистрация: 10.07.2011

Сообщений: 14,522

Записей в блоге: 5

27.07.2016, 00:06

10

EvilFromHell, забавно, что я в DataContractSerializer при сериализации в XML ловил точно такую же ошибку. Решалось просто вырезанием всего, что не проходит проверку XmlConvert.IsXmlChar. Вполне возможно, что JSON реально не ест эти символы (это именно некорректные символы, а не кириллица, например если суррогатная пара применена с символом, с которой её использование недопустимо). Не уверен, что JSON.Net поможет, хотя я в любом случае его использую во всех случаях работы с JSON. Слишком удобно чтобы отказываться.



1



Понравилась статья? Поделить с друзьями:
  • Ошибка двигателя шкода фабия
  • Ошибка двигателя фиат альбеа
  • Ошибка двигателя p2a00 теана
  • Ошибка двигателя check engine
  • Ошибка входа пользователя гость