为什么json_encode返回一个空字符串


107

我有一个带有3个嵌套数组的简单php结构。

我不使用特定的对象,而是使用2个嵌套循环构建数组。

这是我要转换为Json的数组的var_dump的示例。

array (size=2)
  'tram B' => 
    array (size=2)
      0 => 
        array (size=3)
          'name' => string 'Ile Verte' (length=9)
          'distance' => int 298
          'stationID' => int 762
      1 => 
        array (size=3)
          'name' => string 'La Tronche Hôpital' (length=18)
          'distance' => int 425
          'stationID' => int 771
  16 => 
    array (size=4)
      0 => 
        array (size=3)
          'name' => string 'Bastille' (length=8)
          'distance' => int 531
          'stationID' => int 397
      1 => 
        array (size=3)
          'name' => string 'Xavier Jouvin' (length=13)
          'distance' => int 589
          'stationID' => int 438

在另一个脚本中,我具有类似的结构并且json_encode工作正常。所以我不明白为什么json_encode在这里不起作用。

编辑:似乎与编码有问题。当mb_detect_encoding返回ASCII,该json_encode作品但当它返回UTF8,它不工作了。

Edit2:json_last_error()返回JSON_ERROR_UTF8,表示:格式错误的UTF-8字符,可能编码不正确


PHP手册说,This function only works with UTF-8 encoded data.因此编码应该没有任何问题。
MahanGM 2013年

13
在将字符串传递给之前,请尝试utf8_encode()name数组字段上使用json_encode()
MahanGM

谢谢 !我只是来解决这个问题的解决方案。
Matthieu Riegler,2013年

是的,看到答案了。祝好运。
MahanGM

3
使用JSON_PARTIAL_OUTPUT_ON_ERROR选项查看问题(例如,带有UTF8的字段为空)。
彼得·克劳斯

Answers:


255

经过2个小时的挖掘(参考编辑)

我发现以下内容:

  • 就我而言,这是编码问题
  • mb_detect_encoding 返回错误的响应,某些字符串可能不是UTF-8
  • utf8_encode()在这些字符串上使用解决了我的问题,但请参阅下面的注释

这是一个递归函数,可以强制将数组中包含的所有字符串转换为UTF-8:

function utf8ize($d) {
    if (is_array($d)) {
        foreach ($d as $k => $v) {
            $d[$k] = utf8ize($v);
        }
    } else if (is_string ($d)) {
        return utf8_encode($d);
    }
    return $d;
}

像这样简单地使用它:

echo json_encode(utf8ize($data));

注意:utf8_encode()根据文档将ISO-8859-1字符串编码为UTF-8,因此,如不确定注释和其他解决方案中所述,如果不确定输入编码iconv()mb_convert_encoding()可能是更好的选择。


4
感谢您的解决方案...但是,请注意:将更} else {改为} else if (is_string ($d)) {;否则,您将把所有内容都更改为字符串(例如INT将变为STRING)。
Paul Peelen 2014年

3
你刚刚救了我的命。我要结束所有工作,直到找到此功能!!谢谢。
silversunhunter

2
WTF!感谢您分享您的解决方案。我可以看到这需要花很多时间才能弄清楚,对于您这样做和分享,我深表感谢。
克里斯,2016年

1
经过三天的调试,我现在可以吻你。
AJB

2
如果只是从数据库中读取,则使用$ conn-> set_charset(“ utf8”);。
安德鲁·布里格斯

36

Matthieu Riegler提出了一个非常好的解决方案,但是我也不得不对其稍作修改以处理对象:

function utf8ize($d) {
    if (is_array($d)) 
        foreach ($d as $k => $v) 
            $d[$k] = utf8ize($v);

     else if(is_object($d))
        foreach ($d as $k => $v) 
            $d->$k = utf8ize($v);

     else 
        return utf8_encode($d);

    return $d;
}

还有一点需要注意:json_last_error()可能有助于调试json_encode()/ json_encode()函数。


它不应该是elseif不是else if?(即无空白)。
Uwe Keim

2
@UweKeim根据PHP文档“ elseif,否则,如果仅在使用大括号时将被视为完全相同”,这意味着它们是等效的,只要您不使用冒号即可,例如if(): elseif:
Adam Bubela

1
做得好。PHP是垃圾,像您这样的人不会将其转储。
Lonnie Best

else if(is_int($d)||is_bool($d)) return $d;由于以下原因,您应该在最后一个之前插入a :{"success":true, "message":"Ⲃⲟⲟ𝓵ⲉⲁⲛ ⲁⲛⲇ Ⲓⲛϯⲉ𝓰ⲉꞅ𝛓"}
David Refoua

就像@ paul-peelen推荐给@ matthieu-riegler一样:将最后一个更改elseelse if(is_string ($d)); 否则,您将把所有内容都更改为字符串(例如INT将变为STRING)。
布鲁诺·塞拉诺

30

对我来说,此问题的答案是charset=utf8在我的PDO连接中设置。

$dbo = new PDO('mysql:host=localhost;dbname=yourdb;charset=utf8', $username, $password);

2
或在mysqli函数中:mysqli_set_charset($ connection,“ utf8”);
user18099

这是我解决方案的提示。msqli连接的原因稍有不同。$mysqli->set_charset("utf8");完成数据库处理后再调用即可。
MaggusK '18 -10-1

utf8mb4在最新的MySQL版本中使用。utf8已过时。
Dharman

10

Adam Bubela还提出了一个非常好的解决方案,它可以帮助我解决我的问题,这是简化的函数:

function utf8ize($d)
{ 
    if (is_array($d) || is_object($d))
        foreach ($d as &$v) $v = utf8ize($v);
    else
        return utf8_encode($d);

    return $d;
}

1
我喜欢它,因为它保留了密钥。
dev0

7

我在PHP 5.6上有完全相同的问题。我在Windows 7上使用Open Server + Nginx。所有字符集都设置为UTF-8。理论上,根据官方文件,标志

JSON_UNESCAPED_UNICODE

应该解决这个问题。不幸的是,这不是我的情况。我不知道为什么。上面的所有代码片段都不能解决我的问题,因此我找到了自己的实现。我相信它可以帮助某人。至少,俄语字母通过了测试。

function utf8ize($d) {
    if (is_array($d) || is_object($d)) {
        foreach ($d as &$v) $v = utf8ize($v);
    } else {
        $enc   = mb_detect_encoding($d);

        $value = iconv($enc, 'UTF-8', $d);
        return $value;
    }

    return $d;
}

4

此已接受的答案有效。但是,如果您像以前那样从MySQL获取数据,则有一种更简单的方法。

打开数据库后,在查询之前可以使用mysqli设置字符集,如下所示:

/* change character set to utf8 | Procedural*/
if (!mysqli_set_charset($link, "utf8")) {
    printf("Error loading character set utf8: %s\n", mysqli_error($link));
    exit();
}

要么

/* change character set to utf8 | Object Oriented*/
if (!$mysqli->set_charset("utf8")) {
        printf("Error loading character set utf8: %s\n", $mysqli->error);
        exit();
 }

链接:http//php.net/manual/en/mysqli.set-charset.php


4

我在运行旧版本的PHP(5.2)的服务器上遇到此问题。我正在使用JSON_FORCE_OBJECT标志,并且显然直到5.3才支持

因此,如果您使用该标志,请确保检查您的版本!

解决方法似乎只是在编码之前强制转换为对象,例如:

json_encode((object)$myvar);

3

返回的mb_detect_encoding可能不正确:

$data = iconv('UTF-8', 'ISO-8859-1', 'La Tronche Hôpital');
var_dump(
    mb_detect_encoding($data),
    mb_detect_encoding($data, array('ISO-8859-1', 'UTF-8'))
);

根据默认的检测顺序,以上内容可能会返回不同的结果,因此该编码被错误地报告为UTF-8。(这是一个更大的例子。)

很可能你的数据不被编码为UTF-8,因此json_encode将返回false。您应该查看在将JSON编码之前将字符串转换为UTF-8:

$fromEncoding = 'ISO-8859-1'; // This depends on the data

array_walk_recursive($array, function (&$value, $key, $fromEncoding) {
    if (is_string($value)) {
        $value = iconv($fromEncoding, 'UTF-8', $value);
    }
}, $fromEncoding);

3

我从ob_get_clean()获取数据,并且遇到了同样的问题,但是上述解决方案对我不起作用。就我而言,解决方案是这样,也许会对某人有所帮助。

$var = mb_convert_encoding($var, 'UTF-8');

2

在这些字符串上使用utf8_encode()解决了我的问题。


1

我已经改善了亚当·布贝拉的答案。当块没有被{和}关闭时,我只是讨厌它。它更干净,您不会引入错误,或者可能是我过去曾经使用过Perl :)

<?php

class App_Updater_String_Util {    
    /**
     * Usage: App_Updater_String_Util::utf8_encode( $data );
     *
     * @param mixed $d
     * @return mixed
     * @see http://stackoverflow.com/questions/19361282/why-would-json-encode-returns-an-empty-string
     */
    public static function utf8_encode($d) {
        if (is_array($d)) {
            foreach ($d as $k => $v) {
                $d[$k] = self::utf8_encode($v);
            }
        } elseif (is_object($d)) {
            foreach ($d as $k => $v) {
                $d->$k = self::utf8_encode($v);
            }
        } elseif (is_scalar($d)) {
            $d = utf8_encode($d);
        }

        return $d;
    }
}

?>


0

有时会出现此问题-您没有通过标头访问控制。

就我而言,如果我在json_encode之前添加了任何回显。它显示结果,否则将出现空白页。

我加了

header('Access-Control-Allow-Origin: *'); 

我的问题解决了。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.