虽然这显然会在不同版本之间发生变化,但当前的错误代码如下
0 = JSON_ERROR_NONE
1 = JSON_ERROR_DEPTH
2 = JSON_ERROR_STATE_MISMATCH
3 = JSON_ERROR_CTRL_CHAR
4 = JSON_ERROR_SYNTAX
5 = JSON_ERROR_UTF8
我只发布这些是为了那些可能试图理解为什么特定的 JSON 文件无法被解码的人。请不要将这些数字硬编码到错误处理程序例程中。
(PHP 5 >= 5.3.0, PHP 7, PHP 8)
json_last_error — 返回最后发生的错误
此函数没有参数。
返回一个整数,其值可以是以下常量之一
常量 | 含义 | 可用性 |
---|---|---|
JSON_ERROR_NONE |
没有发生错误 | |
JSON_ERROR_DEPTH |
已超过最大堆栈深度 | |
JSON_ERROR_STATE_MISMATCH |
无效或格式错误的 JSON | |
JSON_ERROR_CTRL_CHAR |
控制字符错误,可能是编码错误 | |
JSON_ERROR_SYNTAX |
语法错误 | |
JSON_ERROR_UTF8 |
格式错误的 UTF-8 字符,可能是编码错误 | |
JSON_ERROR_RECURSION |
要编码的值中存在一个或多个递归引用 | |
JSON_ERROR_INF_OR_NAN |
要编码的值中存在一个或多个
NAN 或
INF 值 |
|
JSON_ERROR_UNSUPPORTED_TYPE |
给定了一个无法编码的类型的值 | |
JSON_ERROR_INVALID_PROPERTY_NAME |
给定了一个无法编码的属性名 | |
JSON_ERROR_UTF16 |
格式错误的 UTF-16 字符,可能是编码错误 |
示例 #1 json_last_error() 示例
<?php
// 一个有效的 json 字符串
$json[] = '{"Organization": "PHP Documentation Team"}';
// 一个无效的 json 字符串,会导致语法错误
// 在这种情况下,我们使用了 ' 代替 " 用于引号
$json[] = "{'Organization': 'PHP Documentation Team'}";
foreach ($json as $string) {
echo 'Decoding: ' . $string;
json_decode($string);
switch (json_last_error()) {
case JSON_ERROR_NONE:
echo ' - No errors';
break;
case JSON_ERROR_DEPTH:
echo ' - Maximum stack depth exceeded';
break;
case JSON_ERROR_STATE_MISMATCH:
echo ' - Underflow or the modes mismatch';
break;
case JSON_ERROR_CTRL_CHAR:
echo ' - Unexpected control character found';
break;
case JSON_ERROR_SYNTAX:
echo ' - Syntax error, malformed JSON';
break;
case JSON_ERROR_UTF8:
echo ' - Malformed UTF-8 characters, possibly incorrectly encoded';
break;
default:
echo ' - Unknown error';
break;
}
echo PHP_EOL;
}
?>
上面的示例将输出
Decoding: {"Organization": "PHP Documentation Team"} - No errors Decoding: {'Organization': 'PHP Documentation Team'} - Syntax error, malformed JSON
示例 #2 json_last_error() 与 json_encode()
<?php
// 一个无效的 UTF8 序列
$text = "\xB1\x31";
$json = json_encode($text);
$error = json_last_error();
var_dump($json, $error === JSON_ERROR_UTF8);
?>
上面的示例将输出
string(4) "null" bool(true)
示例 #3 json_last_error() 和 JSON_THROW_ON_ERROR
<?php
// 一个无效的 UTF8 序列,会导致 JSON_ERROR_UTF8
json_encode("\xB1\x31");
// 以下不会导致 JSON 错误
json_encode('okay', JSON_THROW_ON_ERROR);
// 全局错误状态没有被前一个 json_encode() 改变
var_dump(json_last_error() === JSON_ERROR_UTF8);
?>
上面的示例将输出
bool(true)
虽然这显然会在不同版本之间发生变化,但当前的错误代码如下
0 = JSON_ERROR_NONE
1 = JSON_ERROR_DEPTH
2 = JSON_ERROR_STATE_MISMATCH
3 = JSON_ERROR_CTRL_CHAR
4 = JSON_ERROR_SYNTAX
5 = JSON_ERROR_UTF8
我只发布这些是为了那些可能试图理解为什么特定的 JSON 文件无法被解码的人。请不要将这些数字硬编码到错误处理程序例程中。
我使用了这个简单的脚本,从 StackOverflow 中切换出来以逃避函数失败
<?php
function utf8ize($d) {
if (is_array($d)) {
foreach ($d as $k => $v) {
$d[$k] = utf8ize($v);
}
} else if (is_string ($d)) {
return utf8_encode($d);
}
return $d;
}
?>
干杯,
Praveen Kumar!
当 json_decode 一个空字符串时,PHP7 会触发语法错误
<?php
json_decode("");
var_dump(json_last_error(), json_last_error_msg());
// PHP 7
int(4)
string(12) "Syntax error"
// PHP 5
int(0)
string(8) "No error"
使用带有 mb_convert_encoding 的代码,您可以 json_encode 一些损坏的 UTF-8 字符
function safe_json_encode($value, $options = 0, $depth = 512) {
$encoded = json_encode($value, $options, $depth);
if ($encoded === false && $value && json_last_error() == JSON_ERROR_UTF8) {
$encoded = json_encode(utf8ize($value), $options, $depth);
}
return $encoded;
}
function utf8ize($mixed) {
if (is_array($mixed)) {
foreach ($mixed as $key => $value) {
$mixed[$key] = utf8ize($value);
}
} elseif (is_string($mixed)) {
return mb_convert_encoding($mixed, "UTF-8", "UTF-8");
}
return $mixed;
}
我只是添加了这条注释,因为我在为实际值引用编写代码时必须这样做。
<?php
echo JSON_ERROR_NONE . ' JSON_ERROR_NONE' . '<br />';
echo JSON_ERROR_DEPTH . ' JSON_ERROR_DEPTH' . '<br />';
echo JSON_ERROR_STATE_MISMATCH . ' JSON_ERROR_STATE_MISMATCH' . '<br />';
echo JSON_ERROR_CTRL_CHAR . ' JSON_ERROR_CTRL_CHAR' . '<br />';
echo JSON_ERROR_SYNTAX . ' JSON_ERROR_SYNTAX' . '<br />';
echo JSON_ERROR_UTF8 . ' JSON_ERROR_UTF8' . '<br />';
echo JSON_ERROR_RECURSION . ' JSON_ERROR_RECURSION' . '<br />';
echo JSON_ERROR_INF_OR_NAN . ' JSON_ERROR_INF_OR_NAN' . '<br />';
echo JSON_ERROR_UNSUPPORTED_TYPE . ' JSON_ERROR_UNSUPPORTED_TYPE' . '<br />';
/*
上面的输出:
0 JSON_ERROR_NONE
1 JSON_ERROR_DEPTH
2 JSON_ERROR_STATE_MISMATCH
3 JSON_ERROR_CTRL_CHAR
4 JSON_ERROR_SYNTAX
5 JSON_ERROR_UTF8
6 JSON_ERROR_RECURSION
7 JSON_ERROR_INF_OR_NAN
8 JSON_ERROR_UNSUPPORTED_TYPE
*/
?>
这是一个相当简单且实用的技巧,用于验证 JSON 字符串。
<?php
function json_validate($string) {
if (is_string($string)) {
@json_decode($string);
return (json_last_error() === JSON_ERROR_NONE);
}
return false;
}
echo (json_validate('{"test": "valid JSON"}') ? "It's a JSON" : "NOT is a JSON"); // 输出 'It's a JSON'
echo (json_validate('{test: valid JSON}') ? "It's a JSON" : "NOT is a JSON"); // 由于缺少引号,输出 'NOT is a JSON'
echo (json_validate(array()) ? "It's a JSON" : "NOT is a JSON"); // 由于参数不是字符串,输出 'NOT is a JSON'
?>
干杯
这里是一个稍微更新的 utf8ize 版本,它添加了以下内容:
* 它使用 iconv 而不是 utf8_encode,这可能会产生更好的结果。
* 它添加了对对象变量的支持。
* 它还更新了数组键值(在我遇到的一个案例中,我必须将键和值都 utf8ize,因为它们是根据用户输入生成的)。
以下是代码。
<?php
function utf8ize($d) {
if (is_array($d)) {
foreach ($d as $k => $v) {
unset($d[$k]);
$d[utf8ize($k)] = utf8ize($v);
}
} else if (is_object($d)) {
$objVars = get_object_vars($d);
foreach($objVars as $key => $value) {
$d->$key = utf8ize($value);
}
} else if (is_string ($d)) {
return iconv('UTF-8', 'UTF-8//IGNORE', utf8_encode($d));
}
return $d;
}
?>