可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have a simple php structure with 3 nested arrays.
I do not use particular objects and I build myself the arrays with 2 nested loops.
Here is a sample of the var_dump of the array I want to convert to Json.
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
In another script I have a similar structure and json_encode
works fine.
So I don\'t understand why json_encode
won\'t work here.
Edit : there seems to be a problem with the encoding. When mb_detect_encoding
returns ASCII, the json_encode
works but when it returns UTF8, it doesn\'t work anymore.
Edit2 : json_last_error()
returns JSON_ERROR_UTF8
which means : Malformed UTF-8 characters, possibly incorrectly encoded.
回答1:
Well after 2 hours of digging (cf Edits)
I found out following :
- In my case it\'s a encoding problem
mb_detect_encoding
returns probably a faulty response, some strings were probably not UTF-8
- using
utf8_encode()
on those string solved my problem.
Here is a recursive function that can force convert to UTF-8 all the strings contained in an array:
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;
}
Use it simply like this:
echo json_encode(utf8ize($data));
回答2:
Matthieu Riegler presented really good solution however I had to slightly modify it to handle objects too:
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;
}
One more note: json_last_error() may be helpful in debugging json_encode()/json_encode() functions.
回答3:
For me, the answer to this problem was setting charset=utf8 in my PDO connection.
ex:$dbo = new PDO(\'mysql:host=localhost;dbname=yourdb;charset=utf8\', $username, $password);
回答4:
Adam Bubela also presented really good solution who helped me solved my problem, and here is the simplified function :
function utf8ize($d)
{
if (is_array($d) || is_object($d))
foreach ($d as &$v) $v = utf8ize($v);
else
return utf8_encode($d);
return $d;
}
回答5:
I ran into this issue on a server running an older version of PHP (5.2). I was using the JSON_FORCE_OBJECT flag, and apparently that isn\'t supported until 5.3
So if you\'re using that flag be sure to check your version!
A workaround appears to be just casting to an object before encoding, like:
json_encode((object)$myvar);
回答6:
The return of mb_detect_encoding
may not be correct:
$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\'))
);
Depending on the default detection order, the above may return different results, so the encoding is falsely being reported as UTF-8. (Here\'s a larger example.)
It is likely that your data is not encoded as UTF-8, so json_encode
is returning false
. You should look at converting your strings to UTF-8 before JSON-encoding:
$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);
回答7:
This accepted answer works. But in case you are getting your data from MySQL (as I was) there is an easier way.
Once you open you database, before you query you can set the character set using mysqli as follows:
/* change character set to utf8 | Procedural*/
if (!mysqli_set_charset($link, \"utf8\")) {
printf(\"Error loading character set utf8: %s\\n\", mysqli_error($link));
exit();
}
OR
/* change character set to utf8 | Object Oriented*/
if (!$mysqli->set_charset(\"utf8\")) {
printf(\"Error loading character set utf8: %s\\n\", $mysqli->error);
exit();
}
LINK:
http://php.net/manual/en/mysqli.set-charset.php
回答8:
using utf8_encode() on those string solved my problem.
回答9:
I have exactly the same problem on PHP 5.6.
I use Open Server + Nginx on Windows 7. All charsets are set to UTF-8.
In theory, according the official documentation, flag
JSON_UNESCAPED_UNICODE
should solve this.
Unfortunately this is not my case. I do not know, why. All snippets above do not solve my problem, thus I have found my own implementation. I believe it could help someone. At least, Russian letters pass the test.
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;
}
回答10:
I have improved Adam Bubela\'s answer.
I just hate it when blocks are not closed by { and }.
It\'s cleaner and you don\'t introduce bugs or maybe it\'s that I did use Perl in the past :)
<?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;
}
}
?>
回答11:
I was getting data from ob_get_clean() and had the same problem, but above solutions don\'t work for me. In my case solution was this, maybe it will help somebody.
$var = mb_convert_encoding($var, \'UTF-8\');