如何在php json_decode中解决JSON_ERROR_UTF8错误?

Jam*_*rzs 48 php parsing json jsonp

我正在尝试这段代码

$json = file_get_contents("http://www.google.com/alerts/preview?q=test&t=7&f=1&l=0&e");
print_r(json_decode(utf8_encode($json), true));

        //////////////

// Define the errors.
$constants = get_defined_constants(true);
$json_errors = array();
foreach ($constants["json"] as $name => $value) {
    if (!strncmp($name, "JSON_ERROR_", 11)) {
        $json_errors[$value] = $name;
    }
}

// Show the errors for different depths.
foreach (range(4, 3, -1) as $depth) {
    var_dump(json_decode($json, true, $depth));
    echo 'Last error: ', $json_errors[json_last_error()], PHP_EOL, PHP_EOL;
}
Run Code Online (Sandbox Code Playgroud)

我已经尝试了很多函数,html_entities_decode,utf8_encode和解码,解码十六进制代码,但我总是得到错误"JSON_ERROR_UTF8".

我该怎么解决这个问题?

Kon*_*tin 74

清理阵列有很好的功能.

我建议你使用像这样的json_encode包装器:

function safe_json_encode($value, $options = 0, $depth = 512, $utfErrorFlag = false) {
    $encoded = json_encode($value, $options, $depth);
    switch (json_last_error()) {
        case JSON_ERROR_NONE:
            return $encoded;
        case JSON_ERROR_DEPTH:
            return 'Maximum stack depth exceeded'; // or trigger_error() or throw new Exception()
        case JSON_ERROR_STATE_MISMATCH:
            return 'Underflow or the modes mismatch'; // or trigger_error() or throw new Exception()
        case JSON_ERROR_CTRL_CHAR:
            return 'Unexpected control character found';
        case JSON_ERROR_SYNTAX:
            return 'Syntax error, malformed JSON'; // or trigger_error() or throw new Exception()
        case JSON_ERROR_UTF8:
            $clean = utf8ize($value);
            if ($utfErrorFlag) {
                return 'UTF8 encoding error'; // or trigger_error() or throw new Exception()
            }
            return safe_json_encode($clean, $options, $depth, true);
        default:
            return 'Unknown error'; // or trigger_error() or throw new Exception()

    }
}

function utf8ize($mixed) {
    if (is_array($mixed)) {
        foreach ($mixed as $key => $value) {
            $mixed[$key] = utf8ize($value);
        }
    } else if (is_string ($mixed)) {
        return utf8_encode($mixed);
    }
    return $mixed;
}
Run Code Online (Sandbox Code Playgroud)

在我的应用程序中,utf8_encode()比iconv()效果更好

  • 几个月后,这导致我的代码中存在令人讨厌的内存峰值.但它的工作时间为99.99%. (2认同)
  • @SteveB我假设你的内存循环是由于这个函数可以进入一个递归循环,因为它调用自身.如果它继续收到错误JSON_ERROR_UTF8,它将被卡住.我添加了第四个参数,允许JSON_ERROR_UTF8案例在该参数为真时调用自身,但是如果它再次失败则将if传递给自己的调用,它将不会继续调用自身.它可以防止无限循环,甚至只是一个高内存循环.缺点是你只允许"一次尝试",但根据我的编码风格,你应该只需要,否则我希望收到错误的通知. (2认同)
  • 尽管有它的名字,utf8_encode 并不是某种“修复我所有的 UTF-8 问题”函数。它只是从 ISO-8859-1 转换为 UTF-8。在实际上不采用 ISO-8859-1 编码的字符串上运行它,将为您提供“有效”但完全无意义的 UTF-8。 (2认同)

And*_*ong 54

你需要简单的代码行:

$input = iconv('UTF-8', 'UTF-8//IGNORE', utf8_encode($input));
$json = json_decode($input);
Run Code Online (Sandbox Code Playgroud)

图片来源:桑乐,我的同伴给了我这个代码.是啊!

  • 多谢,伙计!你救了我的一天! (5认同)

Ric*_*mer 11

除非您能保证输入有效,否则iconv函数几乎毫无价值.请改用mb_convert_encoding.

mb_convert_encoding($value, "UTF-8", "auto");
Run Code Online (Sandbox Code Playgroud)

您可以比"auto"更明确,甚至可以指定以逗号分隔的预期输入编码列表.

最重要的是,处理无效字符时不会导致整个字符串被丢弃(与iconv不同).