Intereting Posts
Является PHP объектно-ориентированным? mysql_num_rows (): предоставленный аргумент не является допустимым ресурсом результата MySQL Как заменить переменную в строке с помощью PHP? Когда я убираю все входные данные, иногда он оставляет в строке строчки (\) и вставляет их в базу данных. Почему это происходит и как я могу это решить? Phalanger не может найти мои php-классы Нужно центрировать уменьшенное изображение Как форматировать данные определенным образом с помощью html и php PDO – Динамический bindParam – значение 0 странного результата Загрузка видео на сервер с помощью PHP Высокая частота Ajax и перегрузка сна MySQL Необходимо дважды войти в систему. Сессии PHP и проблемы с входами в Chrome и Opera Глобальная переменная – соединение с базой данных? Перестроить данные json удалить дублирующее значение в одном дочернем узле PHP включает () перед doctype, вызывая пробел переменная php внутри echo 'html code'

Сериализовать / unserialize PHP-объект-график для JSON

Я хотел, чтобы сериализовать полный PHP-объект-граф в строковое представление JSON и неэтериализовать его обратно на идентичный PHP-объект-граф.

Вот краткое изложение вариантов, которые я рассмотрел, и причины, по которым они не работают для меня:

  • serialize() не делает то, что я хочу, потому что он использует формат, специфичный для PHP. Я хочу формат, который широко поддерживается большинством языков и доступен для чтения / редактирования.

  • json_encode() не делает то, что я хочу, потому что он просто делает простые значения и массивы, а не объекты. (Я фактически использую это в своей реализации, см. Ниже).

  • var_export() не обрабатывает циклические ссылки и не делает то, что я хочу (см. выше.) (обратите внимание, что моя текущая реализация также не обрабатывает круговые ссылки – см. комментарии и ответ ниже для уточнения этой проблемы.)

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

  • Сериализованный не делает то, что я хочу – он фактически не выполняет сериализацию, он анализирует вывод serialize() и создает другое представление, например XML, но не может проанализировать это представление. (он также не поддерживает JSON – XML ​​- очень длинная форма, и я не хочу этого).

Теперь у меня есть рабочая реализация:

https://github.com/mindplay-dk/jsonfreeze

JSON-представление объектного графика выглядит следующим образом:

 { "#type": "Order", "orderNo": 123, "lines": [{ "#type": "OrderLine", "item": "milk \"fuzz\"", "amount": 3, "options": null }, { "#type": "OrderLine", "item": "cookies", "amount": 7, "options": { "#type": "#hash", "flavor": "chocolate", "weight": "1\/2 lb" } }], "paid": true } 

Этот подход предназначен для работы с агрегатом чистой древовидной структуры – не допускаются циклические ссылки, а также несколько ссылок на одни и те же объекты. Другими словами, это не универсальное назначение, например, serialize() и unserialize() которые функционируют для любого PHP-объекта-графика.

В моем первоначальном подходе я использовал сериализованную форму, которая была в основном базовым 0 списком объектов. Первым объектом в списке (число 0) является корень сериализованного объектного графа, любые другие объекты хранятся в том порядке, в котором они найдены.

В текущей реализации представление JSON похоже на исходную древовидную структуру до такой степени, что это возможно, что позволяет фактически работать с представлением JSON объектного графа в JavaScript. Единственное отклонение – это свойство magic #type (префикс # для предотвращения столкновения с именами свойств) и тип #hash , используемый для различения хешей типа array (хранимых как объекты JSON) из регулярных array типов массивов (хранимых как массивы JSON).


Я оставляю эти заметки о предыдущей версии здесь для исторических целей.

Циклические ссылки обрабатываются просто, никогда не сохраняя вложенные объекты внутри сериализованного представления каждого объекта – вместо этого любая объектная ссылка сохраняется как объект JSON с индексом объекта – например {"__oref":2} является ссылкой на объект с индексом 2 в списке объектов.

У меня проблема с ссылками на массивы в моей реализации – когда я var_dump () внутри кода, который восстанавливает ссылки на объекты в массиве, они заполняются, но в какой-то момент массив копируется, и вы получаете пустую копию. Я пробовал помещать & символы везде в коде, но независимо от того, где я передаю по ссылке, конечным результатом является пустой массив.

Готовый скрипт (выше) удовлетворяет моим точным требованиям:

  • Сериализуйте и несериализуйте весь агрегат.

  • Имейте представление JSON, которое близко напоминает исходную структуру данных.

  • Не загрязняйте структуру данных динамически сгенерированными ключами или другими данными.

Он не обрабатывает круговые ссылки. Как указано в комментарии выше, нет правильного способа хранения круговых ссылок или множественных ссылок на один и тот же объект, так как все они равны. Понимая это, я решил, что мой объектный граф должен быть обычным деревом и принял это ограничение как «хорошую вещь».

update : выход может теперь быть отформатирован с отступом, новыми символами и пробелами – для меня было важно иметь удобное для чтения (и удобное для источника) представление для моих целей. (Форматирование может быть включено или отключено по мере необходимости.)

Я не знаю, если это то, что вам нужно, но если вы заинтересованы только в получении публичных свойств объекта, get_object_vars ($ obj) сделает трюк.

 <?php class foo { public $fname = "John"; public $sname = "Doe"; private $status = null; static $type = "person"; } $obj = new foo; print_r( (get_object_vars($obj)) ); print json_encode(get_object_vars($obj)); ?> 

Вывод:

Array ([fname] => John [sname] => Doe)

{ "Имя_файла": "Джон", "SNAME": "Doe"}

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

Динеш.