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

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

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

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

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

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

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

  • Serialized не делает то, что я хочу - он фактически не выполняет сериализацию, он анализирует вывод 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) является корень сериализованного объектного графа, любые другие объекты хранятся в том порядке, в котором они найдены.

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


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

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

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

Ответ 1

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

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

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

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

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

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

Ответ 2

Я не знаю, если это то, что вам нужно, но если вы заинтересованы только в получении публичных свойств объекта, 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));

?>

Будет выводиться:

Массив ([fname] = > John [sname] = > Doe)

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

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

Динеш.