Сериализация и десериализация в формате PHP для 1С:Предприятие 8.х

Сериализация данных для хранения и передачи на сайтах с кодом на PHP выполняется в особом внутреннем формате строки вида: a:3:{i:1;a:0:{}i:2;a:2:{s:5:»title»;s:67:»(C) 2019.Реформация Компьютерных Систем»;s:8:»nav_menu»;i:2;}s:12:»_multiwidget»;i:1;}

Для использования таких данных за пределами среды PHP необходимо выполнять десериализацию таких данных, а для сохранения сериализацию.

В настоящей публикации описан формат сериализации и приведены коды функций для 1С:Предприятие 8.

Формат сериализации

Сериализация — это преобразование данных произвольной структуры в строковую последовательность конечной длины, для которой в последствии может быть выполнено обратное преобразование для получения исходной структуры данных. В PHP подобное преобразование выполняет несколько пар функций, однако основной является пара serialize() и unserialize(). Сериализованные в строки данные имеют вид a:3:{i:1;s:5:»elem1″;i:2;s:5:»elem2″;i:3;s:5:»elem3″;} и удобны для хранения в базе данных.

Скалярные типы:
  • Булево сериализуется как: b:<i>; где <i> это целое числовое значения 0 (Ложь) или 1 (Истина).
  • Целое сериализуется как: i:<i>; где <i> это числовое значение.
  • Число с плавающей точкой сериализуется как (для d подразумевается двойная точность double): d:<f>; где <f> это числовое значение.
  • Строка сериализуется как: s:<i>:»<s>»; где <i> это представленная длина строки <s>, и <s> это сама строка.
Специальные типы:
  • Значение null просто сериализуется как: N;
Составные типы:
  • Массив сериализуется как: a:<i>:{<elements>} где <i> это число элементов в массиве, и <elements> это пустой или непустой набор пар:
    • <key><value> где <key> представляется скалярным типом , и <value> любым сериализуемым значением.

Следует учесть, что Массив в PHP не соответствует концепции массива в 1С, но очень сходен с Соответствием.

  • Объект сериализуется как: O:<i>:»<s>»:<i>:{<properties>} где первый <i> это целое число представляющее длину <s>, и <s> это имя класса (class name prepended with full namespace). Второй  <i> это целое, представляющее число свойств объекта. <properties> это пустой или нет набор пар:
    • <name><value> где <name> это сериализованная строка представляющая имя свойства и <value> любое сериализуемое значение.

Тут имеет место сложность с <name>, поскольку <name> представляется как s:<i>:»<s>»; где <i> это целое представляющее длину <s>. Но значение <s> может быть различным в зависимости от видимости свойства:

      • для public свойства <s> это просто имя свойства.
      • для protected свойства <s> это также просто имя свойства, начинающееся символом «*», заключенным в два NUL-символа (Chr(0)).
      • для private свойства <s> это имя свойства, начинающееся символом «s», заключенным в два NUL-символа.
Другие типы:

Кроме перечисленных существуют и другие случаи как:  R:<i>; который представляет php-ссылку. Этот тип автору не встречался и его обработка алгоритмом не предусмотрена, поэтому в настоящей публикации он не рассматривается.

Реализация для 1С

Любые структуры данных 1С могут быть сериализованы в строку в полном соответствии с форматом PHP, а также почти любые данные сериализованные в среде PHP могут быть десерализованны в 1С. Некоторую неоднозначность вызывает десериализация составных типов, поскольку в PHP составные типы представлены типами Массив и Объект, в то время как 1С предусматривает типы Массив, Структура, Соответствие (а кроме того СписокЗначений, ТаблицаЗначений, ДеревоЗначений). Наиболее точно друг другу соответствует типы php-Массив и 1с-Соответствие, при этом php-индекс тождественен 1с-ключу.

Сериализация

Основная функция общего модуля СериализоватьРНР(Значение, Глубина)

  • Описание: Рекурсивная функция выполняет сериализацию произвольного значения в строк по формату PHP.
  • Параметры:
    • Значение — значение произвольного типа, которое будет сериализовано в формат PHP строки
    • Глубина — глубина рекурсивности для обхода сложных типов нахоящихся в Значении сложного типа
  • Возвращаемое значение: строка сериализации Значения

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

Десериализация

Функция общего модуля ДесериализоватьРНР(СтрокаСериализации, КурсорСтроки=1)
  • Описание: Рекурсивная функция выполняет десериализацию строки, являющейся сериализацией по формату PHP
  • Параметры:
    • СтрокаСериализации — строка, которая будет десериализована
    • КурсорСтроки — числовой, возвращаемый, устанавливает начало десериализации, по умолчанию =1, возвращаемое значение позволяет проконтролировать индекс завершение сериализации
  • Возвращаемое значение: возвращает десериализованное значение скалярного типа Булево, Число, Строка, NULL или Соотвествие

Приведенный код рассчитан на обработку корректной php-сериализации и не обрабатывает возможные ошибки, поэтому в некоторых случаях десериализация может возвратить абракадабру или даже безнадежно зациклиться.

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

Дополнительные функции

Функция общего модуля СредРНР(Строка, НачальныйНомер, ЧислоСимволов) Экспорт
  • Описание: Функция работает аналогично стандартной Сред(), но корректирует значение ЧислоСимволов. Поскольку в PHP используется такая кодировка символов, при которой символы ASCII используют один символ, а символы национальных раскладок используют два, три или четыре символа (длина UTF-8 кода), то указываемая для s:<i>:»<s>»; длина строки php-символов оказывается больше, чем длина строки 1с-символов, если в строке присутствуют национальные символы.
    • Например: s:5:»А+Б»; при указанной php-длине 5, имеет 1с-длину 3, поэтому функция СредРНР(), получив параметр ЧислоСимволов=5, скорректирует его до ЧислоСимволов=3 и возвратит его по ссылке, и возвращаемую подстроку также уменьшит до 3 символов.
  • Параметры:
    • Строка — строка, из который извлекается подстрока
    • НачальныйНомер — числовой, номер первого символа подстроки в Строке
    • ЧислоСимволов — числовой, возвращаемый, первоначальная длина подстроки в php-символах, значение уменьшается на 1 для каждого найденного в подстроке национального символа
  • Возвращаемое значение: Строка

Функция общего модуля СтрДлинаРНР(СтрокаРНР) Экспорт
  • Описание: Функция работает аналогично стандартной СтрДлина(), но измеряет длину строки в байтах кодировки UTF-8, как требует PHP для указания в строке сериализации
  • Параметры: СтрокаРНР — измеряемая строка
  • Возвращаемое значение: количество байтов в строке PHP в кодировке UTF-8

Источники:

© «РеКС» и DrLightman, 2019

Авторское право принадлежит автору.
При использовании ссылка на источник обязательна.
Исходные тексты предоставлены в свободное использования «как есть» без ответственности за последствия.

Добавить комментарий