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

В основе работы localForage лежит идея унифицированного асинхронного API поверх различных механизмов хранения данных в браузере: IndexedDB, WebSQL и localStorage. Независимо от выбранного драйвера, данные проходят этап сериализации при записи и десериализации при чтении. Именно этот слой преобразования становится источником целого класса ошибок, связанных не с самим хранилищем, а с форматом данных и особенностями их преобразования.

Сериализация в контексте localForage почти всегда опирается на JSON.stringify, а десериализация — на JSON.parse. Это накладывает строгие ограничения на типы данных и их структуру.


Базовый механизм преобразования данных

Перед записью любое значение преобразуется в строку:

  • объект → JSON-строка
  • массив → JSON-строка
  • примитивы → строковое представление JSON

При чтении происходит обратное преобразование:

  • JSON-строка → объект JavaScript
  • если парсинг невозможен → ошибка или null (в зависимости от драйвера и сценария)

Ключевая особенность: localForage не хранит «живые» JavaScript-объекты, он хранит их сериализованные представления.


Ограничения JSON и потеря информации

Типы, которые теряются при сериализации

JSON не поддерживает ряд встроенных типов Jav * aScript:

  • Date
  • Map
  • Set
  • undefined
  • функции
  • Symbol
  • циклические структуры

Каждый из этих типов либо преобразуется в упрощённое представление, либо полностью теряется.

Date

const value = { created: new Date() };

После сериализации:

{"created":"2026-06-03T12:00:00.000Z"}

После десериализации это уже строка, а не объект Date.


undefined и функции

{
  a: undefined,
  b: () => {}
}

После сериализации поля будут удалены:

{}

Map и Set

new Map([["a", 1]])

Преобразуется в объект или теряет структуру в зависимости от предварительной обработки, но исходная семантика полностью утрачивается.


Ошибки JSON.parse при чтении данных

Некорректный формат строки

Если в хранилище попадает строка, не соответствующая JSON, возникает ошибка:

  • повреждённые данные
  • ручная запись через другой API
  • конфликт форматов между версиями приложения

Типичный сценарий:

localStorage.setItem("key", "{invalid json}");

При чтении через localForage:

  • JSON.parse выбрасывает исключение SyntaxError

Причины появления некорректного JSON

  1. Ручное вмешательство в storage
  2. Несовместимость версий приложения
  3. Прерывание записи
  4. Ошибки кастомной сериализации
  5. Повреждение данных в IndexedDB

Циклические структуры

JSON не поддерживает циклы:

const a = {};
a.self = a;

При попытке записи через localForage:

  • JSON.stringify выбрасывает TypeError: Converting circular structure to JSON

Это одна из самых частых причин падения записи сложных объектов.


Несовместимость схем данных

Изменение структуры объекта

При обновлении приложения структура данных часто меняется:

  • добавляются поля
  • удаляются поля
  • меняются типы значений

При десериализации старых данных возникают логические ошибки, а не синтаксические.

Пример:

Старая версия:

{ userId: 1 }

Новая версия ожидает:

{ user: { id: 1 } }

localForage корректно возвращает данные, но приложение получает несовместимый формат.


Различия поведения драйверов

Хотя сериализация едина, поведение при ошибках отличается:

localStorage

  • хранит только строки
  • ошибки чаще проявляются при JSON.parse

IndexedDB

  • более устойчив к повреждению структуры
  • может возвращать undefined без явной ошибки

WebSQL (устаревший)

  • нестабильное поведение при повреждённых данных
  • возможны silent failures

Частичные повреждения данных

В IndexedDB возможны ситуации, когда:

  • объект записан не полностью
  • транзакция прервана
  • данные частично обновлены

Результат:

  • валидный JSON, но логически некорректный объект
  • отсутствие части полей
  • неожиданные null

Ошибки при кастомной сериализации

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

Несогласованность encode/decode

encode(value) → string
decode(value) → object

Если функции не симметричны:

  • данные невозможно восстановить
  • возникают скрытые несоответствия типов

Потеря бинарных данных

При попытке сериализовать:

  • ArrayBuffer
  • Blob

через JSON:

  • данные становятся пустыми объектами или строками
  • восстановление невозможно без отдельного слоя кодирования (например, base64)

Проблемы с Unicode и строками

Хотя JSON поддерживает Unicode, проблемы возникают на уровне:

  • неправильной кодировки при записи
  • двойного экранирования
  • некорректной интерпретации суррогатных пар

Пример:

"?" // символ вне BMP

При неверной обработке может:

  • превращаться в \uD834\uDF06
  • теряться при повторной сериализации

Переполнение и лимиты сериализации

При работе с большими объектами:

  • JSON.stringify может вызывать лаги
  • возможны RangeError: Invalid string length
  • браузер может прерывать выполнение скрипта

localForage в этом случае лишь усиливает эффект, поскольку добавляет слой абстракции поверх синхронного сериализатора.


Несоответствие типов при чтении

Даже при успешной десериализации возможны ошибки типов:

  • число → строка (если было сохранено как строка)
  • объект → null (при частичном повреждении)
  • массив → объект (при неверной структуре данных)

Это приводит к скрытым runtime-ошибкам:

  • undefined is not a function
  • Cannot read property of null

Конфликты версий сериализации

При обновлении логики приложения часто меняется:

  • формат ключей
  • структура объектов
  • стратегия хранения

Если старые данные не мигрированы:

  • десериализация проходит успешно
  • но структура становится несовместимой

Типичный сценарий:

  • версия 1: плоский объект
  • версия 2: вложенная структура
  • старая запись интерпретируется как частично валидная

Защита от ошибок сериализации

Для минимизации проблем используются следующие подходы:

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

Итоговая модель поведения ошибок

Ошибки сериализации и десериализации в localForage можно разделить на три группы:

  1. Синтаксические ошибки

    • невозможность распарсить JSON
    • циклические структуры
    • переполнение строки
  2. Семантические ошибки

    • потеря типов
    • несовместимость версий
    • изменение структуры данных
  3. Драйвер-специфические ошибки

    • различия IndexedDB и localStorage
    • частичное повреждение записей
    • нестабильность устаревших механизмов хранения