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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10199017/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 21:37:20  来源:igfitidea点击:

How to solve JSON_ERROR_UTF8 error in php json_decode?

phpjsonparsingjsonp

提问by James Harzs

I am trying this code

我正在尝试此代码

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

I've tried a lot of functions, html_entities_decode, utf8_encode and decode, decoding the hex codes, but I always get the error "JSON_ERROR_UTF8".

我尝试了很多函数,html_entities_decode,utf8_encode 和 decode,解码十六进制代码,但我总是收到错误“JSON_ERROR_UTF8”。

How could I solve this?

我怎么能解决这个问题?

回答by Konstantin

There is a good function to sanitize your arrays.

有一个很好的函数来清理你的数组。

I suggest you use a json_encode wrapper like this :

我建议您使用这样的 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;
}

In my application utf8_encode() works better than iconv()

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

回答by Andy Truong

You need simple line of code:

您需要简单的代码行:

$input = iconv('UTF-8', 'UTF-8//IGNORE', utf8_encode($input));
$json = json_decode($input);

Credit: Sang Le, my teamate gave me this code. Yeah!

信用:桑乐,我的队友给了我这个代码。是的!

回答by Rich Remer

The iconv function is pretty worthless unless you can guarantee the input is valid. Use mb_convert_encoding instead.

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

mb_convert_encoding($value, "UTF-8", "auto");

You can get more explicit than "auto", and even specify a comma-separated list of expected input encodings.

您可以获得比“自动”更明确的信息,甚至可以指定以逗号分隔的预期输入编码列表。

Most importantly, invalid characters will be handled without causing the entire string to be discarded (unlike iconv).

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

回答by Muhammad Tahir

Decoding JSON in PHPDecoding JSON is as simple as encoding it. PHP provides you a handy json_decode function that handles everything for you. If you just pass a valid JSON string into the method, you get an object of type stdClass back. Here's a short example:

在 PHP 中解码 JSON 解码 JSON 就像编码一样简单。PHP 为您提供了一个方便的 json_decode 函数,它可以为您处理所有事情。如果您只是将有效的 JSON 字符串传递给该方法,则会返回一个 stdClass 类型的对象。这是一个简短的例子:

<?php
$string = '{"foo": "bar", "cool": "attr"}';
$result = json_decode($string);

// Result: object(stdClass)#1 (2) { ["foo"]=> string(3) "bar" ["cool"]=> string(4) "attr" }
var_dump($result);

// Prints "bar"
echo $result->foo;

// Prints "attr"
echo $result->cool;
?>

If you want to get an associative array back instead, set the second parameter to true:

如果要取回关联数组,请将第二个参数设置为 true:

<?php
$string = '{"foo": "bar", "cool": "attr"}';
$result = json_decode($string, true);

// Result: array(2) { ["foo"]=> string(3) "bar" ["cool"]=> string(4) "attr" }
var_dump($result);

// Prints "bar"
echo $result['foo'];

// Prints "attr"
echo $result['cool'];
?>

If you expect a very large nested JSON document, you can limit the recursion depth to a certain level. The function will return null and stops parsing if the document is deeper than the given depth.

如果您期望一个非常大的嵌套 JSON 文档,您可以将递归深度限制在某个级别。如果文档比给定的深度更深,该函数将返回 null 并停止解析。

<?php
$string = '{"foo": {"bar": {"cool": "value"}}}';
$result = json_decode($string, true, 2);

// Result: null
var_dump($result);
?>

The last argument works the same as in json_encode, but there is only one bitmask supported currently (which allows you to convert bigints to strings and is only available from PHP 5.4 upwards).We've been working with valid JSON strings until now (aside fromt the null depth error). The next part shows you how to deal with errors.

最后一个参数与 json_encode 中的工作方式相同,但目前仅支持一个位掩码(它允许您将 bigint 转换为字符串,并且仅适用于 PHP 5.4 以上)。我们一直在使用有效的 JSON 字符串直到现在(除了从零深度误差开始)。下一部分将向您展示如何处理错误。

Error-Handling and TestingIf the JSON value could not be parsed or a nesting level deeper than the given (or default) depth is found, NULL is returned from json_decode. This means that no exception is raised by json_encode/json_deocde directly.

错误处理和测试如果无法解析 JSON 值或发现比给定(或默认)深度更深的嵌套级别,则 json_decode 将返回 NULL。这意味着 json_encode/json_deocde 不会直接引发异常。

So how can we identify the cause of the error? The json_last_error function helps here. json_last_error returns an integer error code that can be one of the following constants (taken from here):

那么我们如何确定错误的原因呢?json_last_error 函数在这里有所帮助。json_last_error 返回一个整数错误代码,它可以是以下常量之一(取自此处):

JSON_ERROR_NONE: No error has occurred. JSON_ERROR_DEPTH: The maximum stack depth has been exceeded. JSON_ERROR_STATE_MISMATCH: Invalid or malformed JSON. JSON_ERROR_CTRL_CHAR: Control character error, possibly incorrectly encoded. JSON_ERROR_SYNTAX: Syntax error. JSON_ERROR_UTF8: Malformed UTF-8 characters, possibly incorrectly encoded (since PHP 5.3.3). With those information at hand, we can write a quick parsing helper method that raises a descriptive exception when an error is found.

JSON_ERROR_NONE:未发生错误。JSON_ERROR_DEPTH:已超出最大堆栈深度。JSON_ERROR_STATE_MISMATCH:JSON 无效或格式错误。JSON_ERROR_CTRL_CHAR:控制字符错误,可能编码不正确。JSON_ERROR_SYNTAX:语法错误。JSON_ERROR_UTF8:格式错误的 UTF-8 字符,可能编码不正确(自 PHP 5.3.3 起)。有了这些信息,我们就可以编写一个快速解析辅助方法,在发现错误时引发描述性异常。

<?php
class JsonHandler {

    protected static $_messages = array(
        JSON_ERROR_NONE => 'No error has occurred',
        JSON_ERROR_DEPTH => 'The maximum stack depth has been exceeded',
        JSON_ERROR_STATE_MISMATCH => 'Invalid or malformed JSON',
        JSON_ERROR_CTRL_CHAR => 'Control character error, possibly incorrectly encoded',
        JSON_ERROR_SYNTAX => 'Syntax error',
        JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, possibly incorrectly encoded'
    );

    public static function encode($value, $options = 0) {
        $result = json_encode($value, $options);

        if($result)  {
            return $result;
        }

        throw new RuntimeException(static::$_messages[json_last_error()]);
    }

    public static function decode($json, $assoc = false) {
        $result = json_decode($json, $assoc);

        if($result) {
            return $result;
        }

        throw new RuntimeException(static::$_messages[json_last_error()]);
    }

}
?>

We can now use the exception testing function from the last post about exception handling to test if our exception works correctly.

我们现在可以使用上一篇关于异常处理的文章中的异常测试功能来测试我们的异常是否正常工作。

// Returns "Correctly thrown"
assertException("Syntax error", function() {
    $string = '{"foo": {"bar": {"cool": NONUMBER}}}';
    $result = JsonHandler::decode($string);
});

Note that since PHP 5.3.3, there is a JSON_ERROR_UTF8 error returned when an invalid UTF-8 character is found in the string. This is a strong indication that a different charset than UTF-8 is used. If the incoming string is not under your control, you can use the utf8_encode function to convert it into utf8.

请注意,自 PHP 5.3.3 起,当在字符串中发现无效的 UTF-8 字符时,会返回 JSON_ERROR_UTF8 错误。这强烈表明使用了与 UTF-8 不同的字符集。如果传入的字符串不在您的控制之下,您可以使用 utf8_encode 函数将其转换为 utf8。

<?php echo utf8_encode(json_encode($payload)); ?>

I've been using this in the past to convert data loaded from a legacy MSSQL database that didn't use UTF-8.

过去我一直在使用它来转换从未使用 UTF-8 的旧版 MSSQL 数据库加载的数据。

source

来源

回答by Fil

I solved adding another 'if' to manage objects in the 'utf8ize' function by @Konstantin (I've not used the other function) :

我解决了在@Konstantin 的“utf8ize”函数中添加另一个“if”来管理对象的问题(我没有使用其他函数):

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);
    } else if (is_object($mixed)) {
        $a = (array)$mixed; // from object to array
        return utf8ize($a);
    }
    return $mixed;
}