检测PHP json_decode()中的错误json数据?

iklwldmw  于 2023-02-11  发布在  PHP
关注(0)|答案(8)|浏览(232)

我尝试处理通过json_decode()解析时的错误json数据。我使用以下脚本:

if(!json_decode($_POST)) {
  echo "bad json data!";
  exit;
}

如果$_POST等于:

'{ bar: "baz" }'

然后json_decode很好地处理错误,并吐出“bad json data!";但是,如果我将$_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!

我是否需要编写一个自定义脚本来检测有效的json数据,或者是否有其他一些漂亮的方法来检测它?

wh6knrhe

wh6knrhe1#

以下是关于json_decode的几点说明:

  • 它返回数据,或在出现错误时返回null
  • 当没有错误时,它还可以返回null:当JSON字符串包含null
  • 它会在有警告的地方发出警告--您希望使其消失的警告。

要解决警告问题,一个解决方案是使用@ operator(我不经常推荐使用它,因为它会使调试更加困难...但在这里,没有太多的选择)

$_POST = array(
    'bad data'
);
$data = @json_decode($_POST);

然后,您必须测试$data是否为null--并且,为了避免json_decode在JSON字符串中为null返回null的情况,您可以检查json_last_error,其中 (引号)
返回上次JSON解析发生的最后一个错误(如果有)。
这意味着您必须使用如下代码:

if ($data === null
    && json_last_error() !== JSON_ERROR_NONE) {
    echo "incorrect data";
}
34gzjxbg

34gzjxbg2#

    • 从PHP 7.3**开始,json_decode函数将接受一个新的JSON_THROW_ON_ERROR选项,该选项将让json_decode抛出异常,而不是在出错时返回null。
    • 示例:**
try {  
  json_decode("{", false, 512, JSON_THROW_ON_ERROR);  
}  
catch (\JsonException $exception) {  
  echo $exception->getMessage(); // displays "Syntax error"  
}
qco9c6ql

qco9c6ql3#

您也可以使用json_last_error:http://php.net/manual/en/function.json-last-error.php
文件上说:
返回上次JSON编码/解码期间发生的最后一个错误(如果有)。
下面是一个示例

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;
}
s8vozzvw

s8vozzvw4#

这是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;
}
o0lyfsai

o0lyfsai5#

我刚刚打破了我的头上的一个json语法错误,在什么似乎是完美的json:{"test1":"car", "test2":"auto"}从url编码的字符串。
但在我的例子中,上面的一些是html编码的,因为添加html_entity_decode($string)就可以了。

$ft = json_decode(html_entity_decode(urldecode(filter_input(INPUT_GET, 'ft', FILTER_SANITIZE_STRING))));

希望这能为别人节省一些时间。

nvbavucw

nvbavucw6#

我刚刚花了一个小时浏览了这个页面上所有可能的解决方案。我冒昧地把所有这些可能的解决方案集合到一个函数中,使它更快更容易地尝试和调试。
我希望它能对别人有用。

<?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(']]>', ']]&gt;', $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('&quot;', '"', $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();
?>

我将在这里维护它:https://github.com/zethodderskov/decontaminate-text-in-php/blob/master/decontaminate-text-preparing-it-for-json-decode.php

6l7fqoea

6l7fqoea7#

/**
 * 
 * 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'
            );
    }
}
h4cxqtbf

h4cxqtbf8#

对于PHP 5.2+,请注意第一个检查。

<?php

class JsonUtil {
    static function decode($json, $associative = null, $depth = null) {
        if (strtolower(trim($json)) === "null") {
            return null;
        }
        
        if (is_null($associative)) {
            $res = json_decode($json);
        }
        else {
            if (is_null($depth)) {
                $depth = 512;
            }
            
            $res = json_decode($json, $associative, $depth);
        }
        
        if (is_null($res)) {
            throw new Exception("Unable to decode JSON");
        }
        
        return $res;
    }
}

相关问题