그래서 새로운 JsonSerializable Interface를 우연히 발견했을 때 PHP 객체를 JSON으로 직렬화하는 방법에 대한 정보를 얻기 위해 php.net 을 돌아 다녔습니다 . 그것은 단지의 PHP> = 5.4 불구하고, 나는 5.3.x 환경에서 실행하고 있습니다.
이런 종류의 기능은 어떻게 PHP <5.4를 얻었 습니까?
아직 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;
}
삼)
구현을 좀 더 깔끔하게 정리하여 다시 한 번 확인하겠습니다. 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'
)));
}
}
JsonSerializable