Как игнорировать свойство null с помощью JsonSerializable:: jsonSerialize()?
Скажем, у нас есть простой объект для сериализации с вложенным объектом:
class User implements \JsonSerializable
{
private $name;
private $email;
private $address;
public function jsonSerialize()
{
return [
'name' => $this->name,
'email' => $this->email,
'address' => $this->address
];
}
}
Вложенный объект:
class Address implements \JsonSerializable
{
private $city;
private $state;
public function jsonSerialize()
{
return [
'city' => $this->city,
'state' => $this->state
];
}
}
Мы используем json_encode()
для сериализации, это будет использовать изначально JsonSerializable:: jsonSerialize():
$json = json_encode($user);
Если $name
и $state
равны нулю, как это сделать:
{
"email": "[email protected]",
{
"city": "Paris"
}
}
вместо этого:
{
"name": null,
"email": "[email protected]",
{
"city": "Paris",
"state": null
}
}
Ответы
Ответ 1
wrap array_filter
вокруг возвращаемых массивов, например
public function jsonSerialize()
return array_filter([
'city' => $this->city,
'state' => $this->state
]);
}
Это приведет к тому, что любые записи будут равны false (слабо сравниваются), включая любые нулевые значения, а также 0 и false. Если вам нужно строгое, например, только нули, введите следующий обратный вызов:
function($val) { return !is_null($val); }
Смотрите документацию для array_filter
:
(PHP 4 >= 4.0.6, PHP 5, PHP 7)
Итерирует по каждому значению в массиве, передавая их функции обратного вызова. Если функция обратного вызова возвращает значение true, текущее значение из массива возвращается в массив результатов. Клавиши массива сохраняются.
Другим вариантом было бы использовать JMX Serializer, который является высоко настраиваемым сериализатором для JSON, XML и YAML. Это намного тяжелее. Подробнее см. Исключить свойства null в JMS Serializer.
Ответ 2
Мой комментарий был неправильным, array_walk_recursive()
может изменять значения, но не может отключить их, поэтому я сделал пользовательскую рекурсивную функцию, всего несколько строк больше кода:
<?php
$a = (object) array(
'first' => null,
'second' => 10,
'third' => (object) array(
'second-first' => 100,
'second-second' => null,
'second-third' => 300
),
'fourth' => 20,
'fifth' => null,
'sixth' => 10);
function remove_null_values($a) {
$ret = (is_array($a) ? array() : new stdClass());
foreach ($a as $k => $v) {
if (is_array($v) || is_object($v)) {
if (is_object($ret))
$ret->$k = remove_null_values($v);
else
$ret[$k] = remove_null_values($v);
}
elseif (!is_null($v)) {
if (is_object($ret))
$ret->$k = $v;
else
$ret[$k] = $v;
}
}
return $ret;
}
Вывод:
object(stdClass)#2 (6) {
["first"]=>
NULL
["second"]=>
int(10)
["third"]=>
object(stdClass)#1 (3) {
["second-first"]=>
int(100)
["second-second"]=>
NULL
["second-third"]=>
int(300)
}
["fourth"]=>
int(20)
["fifth"]=>
NULL
["sixth"]=>
int(10)
}
object(stdClass)#3 (4) {
["second"]=>
int(10)
["third"]=>
object(stdClass)#4 (2) {
["second-first"]=>
int(100)
["second-third"]=>
int(300)
}
["fourth"]=>
int(20)
["sixth"]=>
int(10)
}
EDIT: я обновил код для работы как вложенных массивов, так и объектов, в случае, если вам не нужна функция части массивов, это тривиально, чтобы скомпенсировать это, я позволю вам обрабатывать детали