Сериализация объекта PHP в JSON

Итак, я бродил по php.net в поисках информации о сериализации объектов PHP в JSON, когда наткнулся на новый JsonSerializable интерфейс . Это только PHP> = 5.4 , и я работаю в среде 5.3.x.

Как достигается такая функциональность PHP ?

I я еще не очень много работал с JSON, но я пытаюсь поддерживать уровень API в приложении, и сброс объекта данных (, который в противном случае был бы отправлен в представление ) в JSON был бы идеальным.

Если я попытаюсь сериализовать объект напрямую, он вернет пустую строку JSON; это потому, что я предполагаю, что json_encode () не знает, что, черт возьми, делать с объектом. Следует ли мне рекурсивно уменьшить объект в массив, а затем закодировать , что ?


Пример

$data = new Mf_Data();
$data->foo->bar['hello'] = 'world';

echo json_encode ($ data) создает пустой объект:

{}

var_dump ($ data) Однако работает должным образом:

object(Mf_Data)#1 (5) {
  ["_values":"Mf_Data":private]=>
  array(0) {
  }
  ["_children":"Mf_Data":private]=>
  array(1) {
    [0]=>
    array(1) {
      ["foo"]=>
      object(Mf_Data)#2 (5) {
        ["_values":"Mf_Data":private]=>
        array(0) {
        }
        ["_children":"Mf_Data":private]=>
        array(1) {
          [0]=>
          array(1) {
            ["bar"]=>
            object(Mf_Data)#3 (5) {
              ["_values":"Mf_Data":private]=>
              array(1) {
                [0]=>
                array(1) {
                  ["hello"]=>
                  string(5) "world"
                }
              }
              ["_children":"Mf_Data":private]=>
              array(0) {
              }
              ["_parent":"Mf_Data":private]=>
              *RECURSION*
              ["_key":"Mf_Data":private]=>
              string(3) "bar"
              ["_index":"Mf_Data":private]=>
              int(0)
            }
          }
        }
        ["_parent":"Mf_Data":private]=>
        *RECURSION*
        ["_key":"Mf_Data":private]=>
        string(3) "foo"
        ["_index":"Mf_Data":private]=>
        int(0)
      }
    }
  }
  ["_parent":"Mf_Data":private]=>
  NULL
  ["_key":"Mf_Data":private]=>
  NULL
  ["_index":"Mf_Data":private]=>
  int(0)
}

Приложение

1)

Итак, это функция toArray () , которую я разработал для класса Mf_Data :

public function toArray()
{
    $array = (array) $this;
    array_walk_recursive($array, function (&$property) {
        if ($property instanceof Mf_Data) {
            $property = $property->toArray();
        }
    });
    return $array;
}

Однако, поскольку объекты Mf_Data также имеют ссылку на их родительский ( содержащий ) объект, это не выполняется при рекурсии. Однако работает как шарм, когда я удаляю ссылку _parent .

2)

И наконец, последняя функция для преобразования сложного объекта дерева-узла, которую я использовал, была:

// class name - Mf_Data
// exlcuded properties - $_parent, $_index
public function toArray()
{
    $array = get_object_vars($this);
    unset($array['_parent'], $array['_index']);
    array_walk_recursive($array, function (&$property) {
        if (is_object($property) && method_exists($property, 'toArray')) {
            $property = $property->toArray();
        }
    });
    return $array;
}

3)

Я снова продолжаю следить за более чистой реализацией. Использование интерфейсов для проверки instanceof кажется намного чище, чем method_exists () (, однако method_exists () выполняет перекрестное наследование / реализацию ) .

Использование unset () тоже показалось немного запутанным, и кажется, что логику следует реорганизовать в другой метод. Однако эта реализация действительно копирует массив свойств ( из-за array_diff_key ), так что следует учесть.

interface ToMapInterface
{

    function toMap();

    function getToMapProperties();

}

class Node implements ToMapInterface
{

    private $index;
    private $parent;
    private $values = array();

    public function toMap()
    {
        $array = $this->getToMapProperties();
        array_walk_recursive($array, function (&$value) {
            if ($value instanceof ToMapInterface) {
                $value = $value->toMap();
            }
        });
        return $array;
    }

    public function getToMapProperties()
    {
        return array_diff_key(get_object_vars($this), array_flip(array(
            'index', 'parent'
        )));
    }

}

100
задан Dan Lugg 28 May 2015 в 15:30
поделиться