在 PHP json_decode() 中检测错误的 json 数据?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2348152/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Detect bad json data in PHP json_decode()?
提问by soren.qvist
I'm trying handle bad json data when parsed through json_decode(). I'm using the following script:
当通过 json_decode() 解析时,我正在尝试处理错误的 json 数据。我正在使用以下脚本:
if(!json_decode($_POST)) {
echo "bad json data!";
exit;
}
If $_POST equals:
如果 $_POST 等于:
'{ bar: "baz" }'
Then json_decode handles the error fine and spits out "bad json data!"; However, if I set $_POST to something like "invalid data", it gives me:
然后 json_decode 会很好地处理错误并吐出“错误的 json 数据!”;但是,如果我将 $_POST 设置为“无效数据”之类的内容,它会给我:
Warning: json_decode() expects parameter 1 to be string, array given in C:\server\www\myserver.dev\public_html\rivrUI\public_home\index.php on line 6
bad json data!
Do I need to write a custom script to detect valid json data, or is there some other nifty way to detect this?
我是否需要编写自定义脚本来检测有效的 json 数据,还是有其他一些不错的方法可以检测到这一点?
回答by Pascal MARTIN
Here are a couple of things about json_decode:
这里有一些关于json_decode:
- it returns the data, or
nullwhen there is an error - it can also return
nullwhen there is no error : when the JSON string containsnull - it raises a warning where there is a warning -- warning that you want to make disappear.
- 它返回数据,或者
null当有错误时 - 它也可以
null在没有错误时返回:当 JSON 字符串包含null - 它会在有警告的地方发出警告——你想让它消失的警告。
To solve the warning problem, a solution would be to use the @operator(I don't often recommend using it, as it makes debuging a lot more harder... But here, there is not much of a choice):
为了解决警告问题,一个解决方案是使用@运算符(我不经常推荐使用它,因为它使调试更加困难......但在这里,没有太多选择):
$_POST = array(
'bad data'
);
$data = @json_decode($_POST);
You'd then have to test if $datais null-- and, to avoid the case in which json_decodereturns nullfor nullin the JSON string, you could check json_last_error, which (quoting):
然后,您必须测试是否$data为null-- 并且,为了避免在 JSON 字符串中json_decode返回nullfor的情况null,您可以检查json_last_error, which (引用):
Returns the last error (if any) occurred by last JSON parsing.
返回上次 JSON 解析发生的最后一个错误(如果有)。
Which means you'd have to use some code like the following :
这意味着您必须使用如下代码:
if ($data === null
&& json_last_error() !== JSON_ERROR_NONE) {
echo "incorrect data";
}
回答by Doua Beri
You can also use json_last_error : http://php.net/manual/en/function.json-last-error.php
您还可以使用 json_last_error :http://php.net/manual/en/function.json-last-error.php
which as documentation says :
正如文档所说:
Returns the last error (if any) occurred during the last JSON encoding/decoding.
返回上次 JSON 编码/解码期间发生的最后一个错误(如果有)。
here is an example
这是一个例子
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;
}
回答by Harry Bosh
This is how Guzzle handles json
这就是 Guzzle 处理 json 的方式
/**
* Parse the JSON response body and return an array
*
* @return array|string|int|bool|float
* @throws RuntimeException if the response body is not in JSON format
*/
public function json()
{
$data = json_decode((string) $this->body, true);
if (JSON_ERROR_NONE !== json_last_error()) {
throw new RuntimeException('Unable to parse response body into JSON: ' . json_last_error());
}
return $data === null ? array() : $data;
}
回答by dtar
Since PHP 7.3, the json_decode function will accept a new JSON_THROW_ON_ERROR option that will let json_decode throw an exception instead of returning null on error.
自 PHP 7.3 起, json_decode 函数将接受一个新的 JSON_THROW_ON_ERROR 选项,该选项将使 json_decode 抛出异常而不是在出错时返回 null。
Example:
例子:
try {
json_decode("{", false, 512, JSON_THROW_ON_ERROR);
}
catch (\JsonException $exception) {
echo $exception->getMessage(); // displays "Syntax error"
}
回答by Klompenrunner
I just broke my head over a json syntax error in what appeared to be perfect json: {"test1":"car", "test2":"auto"}from a url encoded string.
我刚刚在一个看似完美的 json 中出现了 json 语法错误:{"test1":"car", "test2":"auto"}来自 url 编码的字符串。
But in my case some of the above was html encoded, as adding html_entity_decode($string)did the trick.
但在我的情况下,上面的一些是 html 编码的,因为添加html_entity_decode($string)是诀窍。
$ft = json_decode(html_entity_decode(urldecode(filter_input(INPUT_GET, 'ft', FILTER_SANITIZE_STRING))));
Hopefully this will save someone else some time.
希望这会为其他人节省一些时间。
回答by Zakaria.dem
/**
*
* custom json_decode
* handle json_decode errors
*
* @param type $json_text
* @return type
*/
public static function custom_json_decode($json_text) {
$decoded_array = json_decode($json_text, TRUE);
switch (json_last_error()) {
case JSON_ERROR_NONE:
return array(
"status" => 0,
"value" => $decoded_array
);
case JSON_ERROR_DEPTH:
return array(
"status" => 1,
"value" => 'Maximum stack depth exceeded'
);
case JSON_ERROR_STATE_MISMATCH:
return array(
"status" => 1,
"value" => 'Underflow or the modes mismatch'
);
case JSON_ERROR_CTRL_CHAR:
return array(
"status" => 1,
"value" => 'Unexpected control character found'
);
case JSON_ERROR_SYNTAX:
return array(
"status" => 1,
"value" => 'Syntax error, malformed JSON'
);
case JSON_ERROR_UTF8:
return array(
"status" => 1,
"value" => 'Malformed UTF-8 characters, possibly incorrectly encoded'
);
default:
return array(
"status" => 1,
"value" => 'Unknown error'
);
}
}
回答by Zeth
I just spent an hour going through all the possible solutions on this page. I took the liberty of collective all these possible solutions into one function, to make it quicker and easier to try and debug.
我只花了一个小时浏览了此页面上所有可能的解决方案。我冒昧地将所有这些可能的解决方案集中到一个功能中,以便更快、更轻松地尝试和调试。
I hope it can be of use to someone else.
我希望它可以对其他人有用。
<?php
/**
* Decontaminate text
*
* Primary sources:
* - https://stackoverflow.com/questions/17219916/json-decode-returns-json-error-syntax-but-online-formatter-says-the-json-is-ok
* - https://stackoverflow.com/questions/2348152/detect-bad-json-data-in-php-json-decode
*/
function decontaminate_text(
$text,
$remove_tags = true,
$remove_line_breaks = true,
$remove_BOM = true,
$ensure_utf8_encoding = true,
$ensure_quotes_are_properly_displayed = true,
$decode_html_entities = true
){
if ( '' != $text && is_string( $text ) ) {
$text = preg_replace( '@<(script|style)[^>]*?>.*?</\1>@si', '', $text );
$text = str_replace(']]>', ']]>', $text);
if( $remove_tags ){
// Which tags to allow (none!)
// $text = strip_tags($text, '<p>,<strong>,<span>,<a>');
$text = strip_tags($text, '');
}
if( $remove_line_breaks ){
$text = preg_replace('/[\r\n\t ]+/', ' ', $text);
$text = trim( $text );
}
if( $remove_BOM ){
// Source: https://stackoverflow.com/a/31594983/1766219
if( 0 === strpos( bin2hex( $text ), 'efbbbf' ) ){
$text = substr( $text, 3 );
}
}
if( $ensure_utf8_encoding ){
// Check if UTF8-encoding
if( utf8_encode( utf8_decode( $text ) ) != $text ){
$text = mb_convert_encoding( $text, 'utf-8', 'utf-8' );
}
}
if( $ensure_quotes_are_properly_displayed ){
$text = str_replace('"', '"', $text);
}
if( $decode_html_entities ){
$text = html_entity_decode( $text );
}
/**
* Other things to try
* - the chr-function: https://stackoverflow.com/a/20845642/1766219
* - stripslashes (THIS ONE BROKE MY JSON DECODING, AFTER IT STARTED WORKING, THOUGH): https://stackoverflow.com/a/28540745/1766219
* - This (improved?) JSON-decoder didn't help me, but it sure looks fancy: https://stackoverflow.com/a/43694325/1766219
*/
}
return $text;
}
// Example use
$text = decontaminate_text( $text );
// $text = decontaminate_text( $text, false ); // Debug attempt 1
// $text = decontaminate_text( $text, false, false ); // Debug attempt 2
// $text = decontaminate_text( $text, false, false, false ); // Debug attempt 3
$decoded_text = json_decode( $text, true );
echo json_last_error_msg() . ' - ' . json_last_error();
?>
I'll maintain it here: https://github.com/zethodderskov/decontaminate-text-in-php/blob/master/decontaminate-text-preparing-it-for-json-decode.php
我会在这里维护它:https: //github.com/zethodderskov/decontaminate-text-in-php/blob/master/decontaminate-text-preparing-it-for-json-decode.php

