【发布时间】:2011-10-12 14:10:08
【问题描述】:
我所有的 AJAX 请求都是 json 格式,并在 javascript 中解析。
如何防止空值显示在 HTML 页面中,而无需在 javascript 中为每个 json 值编写 if 语句?
或者我应该编写一个自定义 PHP 函数来将数组编码为 json,而不是使用 json_encode(),这样它就不会显示“null”?
【问题讨论】:
我所有的 AJAX 请求都是 json 格式,并在 javascript 中解析。
如何防止空值显示在 HTML 页面中,而无需在 javascript 中为每个 json 值编写 if 语句?
或者我应该编写一个自定义 PHP 函数来将数组编码为 json,而不是使用 json_encode(),这样它就不会显示“null”?
【问题讨论】:
在服务器端使用 PHP,
您可以在json_encode 之前使用array_filter。
array_filter 不带第二个参数会删除条目数组的 null 元素,例如:
$object= array(
0 => 'foo',
1 => false,
2 => -1,
3 => null,
4 => ''
);
$object = (object) array_filter((array) $object);
$result = json_encode($object);
$result 包含:
{"0":"foo","2":-1}
如您所见,null 元素已被移除。
【讨论】:
我将添加到已接受的答案中,因为这仅在您拥有一维对象或数组时才有效。如果有任何数组或对象嵌套,那么为了使公认的解决方案起作用,您必须创建某种递归数组过滤器。不理想。
我的同事和我想出的最佳解决方案是在 JSON 字符串从服务器返回之前实际执行正则表达式。
$json = json_encode($complexObject);
echo preg_replace('/,\s*"[^"]+":null|"[^"]+":null,?/', '', $json);
正则表达式将删除格式为,"key":null 的字符串中的所有位置,包括前导逗号和键开头之间的任何空格。之后它还会匹配"key":null,,以确保在 JSON 对象的开头没有找到空值。
这不是一个理想的解决方案,但它比创建递归数组过滤器要好得多,因为对象可能有几个维度深。更好的解决方案是 json_encode 有一个标志,可以让您指定是否希望空条目保留在输出字符串中。
【讨论】:
json_encode 本身支持它会很好,但我非常怀疑这是否会发生。至少在我的经验中,PHP 在多维方面往往很弱。
null 之前添加了 `?` 以说明何时设置 JSON_PRETTY_PRINT 并且键和值之间有空格。
只删除NULL,但保留FALSE、''和0:
function is_not_null($var)
{
return !is_null($var);
}
echo json_encode(array_filter((array) $object, 'is_not_null'));
【讨论】:
public function __toString() {
$obj = clone $this;
$keys = get_object_vars($obj);
foreach ($keys as $key => $value) {
if (!$value) {
unset($obj->{$key});
}
}
return json_encode($obj);
}
【讨论】:
在 javascript 端使用原生 JSON.stringify 方法怎么样? 您可以设置第二个参数,一个函数来删除具有空值的键。 如果返回 undefined,则该属性不包含在输出 JSON 字符串中(请查看https://developer.mozilla.org/en-US/docs/Using_native_JSON#The_replacer_parameter 的“替换器参数”文档)。
function removeNulls(obj) {
var str = JSON.stringify(obj, function(key, val) {
if (val == null) return undefined;
return val;
});
return JSON.parse(str);
}
然后你可以通过调用得到一个“标准化”的 JSON 对象:
var obj = removeNulls(obj);
【讨论】:
echo json_encode(array_filter((array) $object, function($val) {
return !empty($val);
}));
【讨论】:
class Foo implements JsonSerializable
{
public $param1;
public $param2;
public function jsonSerialize()
{
return array_filter((array) $this, function ($var) {
return !is_null($var);
});
}
}
public function testJsonSerialization()
{
$expectedJson = '{"param1":true}';
$foo = new Foo();
$foo->param1 = true;
$foo->param2 = null;
$this->assertEquals(
$expectedJson,
json_encode($foo)
);
}`
当然,您可以使用自定义 jsonSerialize 方法创建抽象类,并由此扩展您的所有 DTO
【讨论】: