Vì vậy, tôi đã lang thang trên php.net để tìm thông tin về việc tuần tự hóa các đối tượng PHP thành JSON, khi tôi tình cờ tìm thấy Giao diện JsonSerializable mới . Tuy nhiên, nó chỉ có PHP> = 5.4 và tôi đang chạy trong môi trường 5.3.x.
Làm thế nào để loại chức năng này đạt được PHP <5,4 ?
Tôi chưa làm việc nhiều với JSON, nhưng tôi đang cố gắng hỗ trợ một lớp API trong một ứng dụng và kết xuất đối tượng dữ liệu ( nếu không sẽ được gửi đến chế độ xem ) vào JSON sẽ rất hoàn hảo.
Nếu tôi cố gắng tuần tự hóa đối tượng trực tiếp, nó sẽ trả về một chuỗi JSON trống; đó là bởi vì tôi cho rằng json_encode()
không biết phải làm gì với đối tượng. Tôi có nên giảm đệ quy đối tượng thành một mảng và sau đó mã hóa nó không?
Thí dụ
$data = new Mf_Data();
$data->foo->bar['hello'] = 'world';
echo json_encode($data)
tạo ra một đối tượng trống:
{}
var_dump($data)
tuy nhiên, hoạt động như mong đợi:
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)
}
Phụ lục
1)
Vì vậy, đây là toArray()
hàm tôi đã nghĩ ra cho Mf_Data
lớp:
public function toArray()
{
$array = (array) $this;
array_walk_recursive($array, function (&$property) {
if ($property instanceof Mf_Data) {
$property = $property->toArray();
}
});
return $array;
}
Tuy nhiên vì các Mf_Data
đối tượng cũng có tham chiếu đến đối tượng cha ( chứa ) của chúng, điều này không thành công với đệ quy. Hoạt động như một sự quyến rũ mặc dù khi tôi xóa _parent
tham chiếu.
2)
Chỉ cần theo dõi, hàm cuối cùng để biến đổi một đối tượng nút cây phức tạp mà tôi đã sử dụng là:
// 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)
Tôi đang theo dõi lại, với cách triển khai gọn gàng hơn một chút. Việc sử dụng các giao diện để instanceof
kiểm tra có vẻ gọn gàng hơn nhiều method_exists()
( tuy nhiên, method_exists()
việc thực hiện / kế thừa chéo ).
Việc sử dụng cũng unset()
có vẻ hơi lộn xộn và có vẻ như logic nên được cấu trúc lại thành một phương pháp khác. Tuy nhiên, việc triển khai này thực hiện sao chép mảng thuộc tính ( doarray_diff_key
), vì vậy cần xem xét điều gì đó.
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