UTF-8 中的值在 JSON 中被编码为 NULL

问题描述 投票:0回答:5

我有一组关键字通过 JSON 从数据库(编码的 UTF-8)传递,其中一些可能具有特殊字符,如 é、è、ç 等。这用作自动完成器的一部分。示例:

array('Coffee', 'Cappuccino', 'Café');

我应该补充一点,来自数据库的数组将是:

array('Coffee', 'Cappuccino', 'Café');

但是 JSON 编码为:

["coffee", "cappuccino", null];

如果我通过 print_r() 打印这些,它们在 UTF-8 编码的网页上显示得很好,但是如果我想使用 print_r($array 查看数组,则使用 text/plain ,则咖啡馆会显示为“café” );退出();.

如果我在编码为 JSON 之前使用 utf8_encode() 进行编码,则效果很好,但网页上打印的内容是“café”而不是“café”。

也很奇怪,但是 json_last_error() 被视为未定义的函数,但 json_decode() 和 json_encode() 工作正常。

关于如何从数据库获取 UTF-8 编码数据并在整个过程中表现相同的任何想法?

EIDT:这是抓取关键字并将它们放入单个数组的 PHP 函数:

private function get_keywords() 
{
    global $db, $json;

    $output = array();

    $db->query("SELECT keywords FROM listings");

    while ($r = $db->get_array())
    {
        $split = explode(",", $r['keywords']);

        foreach ($split as $s)
        {
            $s = trim($s);
            if ($s != "" && !in_array($s, $output)) $output[] = strtolower($s);
        }
    }

    $json->echo_json($output);
}

json::echo_json 方法只是编码、设置标题并打印它(用于 Prototype)

编辑:数据库连接方法:

function connect()
{

    if ($this->set['sql_connect'])
    {
        $this->connection = @mysql_connect( $this->set['sql_host'], $this->set['sql_user'], $this->set['sql_pass'])
                OR $this->debug( "Connection Error", mysql_errno() .": ". mysql_error());
        $this->db = @mysql_select_db( $this->set['sql_name'], $this->connection)
                OR $this->debug( "Database Error", "Cannot Select Database '". $this->set['sql_name'] ."'");

        $this->is_connected = TRUE;
    }

    return TRUE;
}

更多更新: 我运行的简单 PHP 脚本:

echo json_encode( array("Café") ); // ["Caf\u00e9"]
echo json_encode( array("Café") ); // null
php json utf-8
5个回答
11
投票

原因可能是当前客户端角色设置。一个简单的解决方案可能是设置客户端

mysql_query('SET CHARACTER SET utf8')
在运行
SELECT
查询之前。

更新(2014 年 6 月)

自 PHP 5.5.0 起,不推荐使用 mysql 扩展。现在推荐使用mysqli。另外,进一步阅读后 - 应避免使用上述设置客户端集的方式,原因包括安全性

我还没有测试过,但这应该是一个不错的替代品:

$mysqli = new mysqli("localhost", "my_user", "my_password", "my_db");
if (!$mysqli->set_charset('utf8')) {
    printf("Error loading character set utf8: %s\n", $mysqli->error);
} else {
    printf("Current character set: %s\n", $mysqli->character_set_name());
}

或使用连接参数:

$conn = mysqli_connect("localhost", "my_user", "my_password", "my_db");
if (!mysqli_set_charset($conn, "utf8")) {
    # TODO - Error: Unable to set the character set
    exit;
}

3
投票

json_encode
似乎正在删除包含无效字符的字符串。您的 UTF-8 数据可能未以正确的形式从数据库到达。

查看您给出的示例,我的疯狂猜测是您的数据库连接不是UTF-8编码,而是提供ISO-8859-1字符。

初始化连接后可以尝试一下

SET NAMES utf8;
吗?


3
投票

我尝试了你的代码示例,如下所示:

[~]> cat utf.php 
<?php
$arr = array('Coffee', 'Cappuccino', 'Café');
print json_encode($arr);
[~]> php utf.php 
["Coffee","Cappuccino","Caf\u00e9"]
[~]>

基于此,我想说,如果源数据确实是 UTF-8,那么 json_encode 就可以正常工作。如果不是,那么这就是你得到 null 的地方。为什么不是,根据这些信息我无法判断。


1
投票

在执行 json_encode() 之前尝试通过此函数发送数组:

<?php

function utf8json($inArray) {

    static $depth = 0;

    /* our return object */
    $newArray = array();

    /* safety recursion limit */
    $depth ++;
    if($depth >= '30') {
        return false;
    }

    /* step through inArray */
    foreach($inArray as $key=>$val) {
        if(is_array($val)) {
            /* recurse on array elements */
            $newArray[$key] = utf8json($inArray);
        } else {
            /* encode string values */
            $newArray[$key] = utf8_encode($val);
        }
    }

    /* return utf8 encoded array */
    return $newArray;
}
?>

摘自 phpnet @ http://php.net/manual/en/function.json-encode.php 上的评论。

该函数基本上循环遍历数组元素,也许您对数组本身进行了 utf-8 编码?


0
投票

我对 utf8 数据进行编码的解决方案是:

$jsonArray = addslashes(json_encode($array, JSON_FORCE_OBJECT|JSON_UNESCAPED_UNICODE))
© www.soinside.com 2019 - 2024. All rights reserved.