53

我正在尝试这段代码

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

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

我怎么能解决这个问题?

4

6 回答 6

77

有一个很好的功能可以清理您的数组。

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

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

于 2014-11-05T15:32:10.100 回答
56

您需要简单的代码行:

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

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

于 2013-06-19T03:31:15.177 回答
14

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

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

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

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

于 2014-06-25T17:22:18.720 回答
1

没有灵丹妙药可以“解决”编码问题;你必须了解你有什么编码,然后转换它。

计算机最终传输和存储二进制数据;为了使二进制数据有用,我们设计了这样的代码:“这个二进制字符串代表一个'a',一个代表一个'b',另一个代表商务西装悬浮表情符号️”。 UTF-8(稍微简化一点)只是其中一种编码。其他编码有 ASCII、ISO-8859-1、Windows Code Page 1252 和 Shift-JIS 等名称。

如果您只知道一个字符串不是“UTF-8” ,那么您就无法将其转换为 UTF-8,因为您不知道第一个字符应该是“a”还是“️”。

如果你知道你的字符串是什么编码,你可以使用 PHP 中的三个函数中的任何一个;根据您安装的 PHP,部分或全部可能不可用,但它们是您想要的。

请注意,mb_convert_encoding 允许您省略说明当前编码的参数。这不会自动计算出正确的编码,它只是使用您控制的全局设置。

PHP 中还提供了另外两个名称错误的函数:utf8_encodeutf8_decode。这些只是上述三个函数的极其有限的版本:它们只能从 ISO-8859-1 转换为 UTF-8 并返回。如果您的字符串不在该编码中(并且您不希望它是),这些函数将无济于事。它们可能会使您的错误消失,但这与修复数据不同。

于 2021-04-04T22:33:01.677 回答
0

在 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;
?>

如果您想取回关联数组,请将第二个参数设置为 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'];
?>

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

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

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

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

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

那么我们如何确定错误的原因呢?json_last_error 函数在这里有所帮助。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 字符,可能编码不正确(自 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()]);
    }

}
?>

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

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

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

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

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

资源

于 2019-08-05T08:14:01.990 回答
-1

我通过@Konstantin解决了添加另一个'if'来管理'utf8ize'函数中的对象(我没有使用其他函数):

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;
}
于 2020-04-21T22:02:19.453 回答