JSON Сериализация класса php с помощью JsonSerializable

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

Например, мы можем это сделать с помощью такой конструкции.

<?php
class Test {
	public $a = 'A';
	public $b = 'B';
}

$b = new Test();
echo json_encode($b);
?>

На выходе мы получим вот такой результат:

{"a":"A","b":"B"}

Но как быть, например, если у класса у нас есть приватные или продектед свойства, а при сериализации они все равно должны быть видны. Например, вот такой пример:

<?php
class Test {
	protected $a = 'A';
	protected $b;
}

$b = new Test();
echo json_encode($b);

На выходе мы получим просто пустой объект {}.

Для исправления этой проблемы в PHP существует интерфейс JsonSerializable, который и позволяет нам сериализовать класс по каки-то условиям. Например,

<?php
class Test implements JsonSerializable {
	protected $a = 'A';
	protected $b = true;
	public function jsonSerialize() {
		$result = array(
			'value' => $this->a,
			'result' => $this->b
		);
		return $result;
	}
}
$b = new Test();
echo json_encode($b);
?>

Нам нужно лишь реализовать метод jsonSerialize. Теперь на выходе у нас будет вот такой результат:

{"value":"A","result":true}

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

И базовый класс модели сериализации выглядит уже вот так.

<?php namespace App\Model;
class BaseJsonModel extends Base implements \JsonSerializable {
	public function __construct() {
		parent::__construct();
	}
	public function jsonSerialize() {
		$reflect = new \ReflectionClass($this);
		$props   = $reflect->getProperties(\ReflectionProperty::IS_PUBLIC | \ReflectionProperty::IS_PROTECTED);
		$result = array();
		foreach($props as $item) {
			$name = $item->getName();
			$result[$name] = $this->$name;
		}
		return $result;
	}
	public function __toString() {
		return json_encode($this->jsonSerialize(), JSON_UNESCAPED_UNICODE);
	}
}