json_encode将带有Unicode版权字符的字符串编码为null?

6

我在JSON编码特殊字符时遇到了麻烦。这些字符在我的电脑、记事本、浏览器甚至数据库中都能正常显示,但是它们无法进行JSON编码。以下是一个示例:

<?
$array['copyright_str'] = "Copyright site.com © 2011-2012";
echo json_encode($array);
?>

在site.com之后的版权符号是导致JSON字符串输出为{"copyright_str":null}的原因。虽然这很简单,但我有用户将个人资料数据输入到数据库中,其中可能包含任何内容。当这些奇怪的字符出现时,会破坏事情的正常运行。有什么好的解决方案吗?我编写的API在很大程度上依赖于从数据库返回数据和以JSON形式打印字符串。

我的多字节设置如下:

     php -e phpinfo.php  | grep mb
    Configure Command =>  './configure'  '--enable-bcmath' '--enable-calendar' '--enable-dbase' '--enable-exif' '--enable-ftp' '--enable-gd-native-ttf' '--enable-libxml' '--enable-magic-quotes' '--enable-mbstring' '--enable-pdo=shared' '--enable-sockets' '--enable-zip' '--prefix=/usr/local' '--with-apxs2=/usr/local/apache/bin/apxs' '--with-bz2' '--with-curl=/opt/curlssl/' '--with-curlwrappers' '--with-freetype-dir=/usr' '--with-gd' '--with-imap=/opt/php_with_imap_client/' '--with-imap-ssl=/usr' '--with-jpeg-dir=/usr' '--with-kerberos' '--with-libdir=lib64' '--with-libexpat-dir=/usr' '--with-libxml-dir=/opt/xml2/' '--with-mcrypt=/opt/libmcrypt/' '--with-mhash=/opt/mhash/' '--with-mysql=/usr' '--with-mysql-sock=/var/lib/mysql/mysql.sock' '--with-mysqli=/usr/bin/mysql_config' '--with-openssl=/usr' '--with-openssl-dir=/usr' '--with-pcre-regex=/opt/pcre' '--with-pdo-mysql=shared' '--with-pdo-sqlite=shared' '--with-pic' '--with-png-dir=/usr' '--with-sqlite=shared' '--with-ttf' '--with-xmlrpc' '--with-xpm-dir=/usr' '--with-zlib' '--with-zlib-dir=/usr'
    xmlrpc_error_number => 0 => 0
    mbstring
    Multibyte string engine => libmbfl
    mbstring extension makes use of "streamable kanji code filter and converter", which is distributed under the GNU Lesser General Public License version 2.1.
    mbstring.detect_order => no value => no value
    mbstring.encoding_translation => Off => Off
    mbstring.func_overload => 0 => 0
    mbstring.http_input => pass => pass
    mbstring.http_output => pass => pass
    mbstring.internal_encoding => no value => no value
    mbstring.language => neutral => neutral
    mbstring.strict_detection => Off => Off
    mbstring.substitute_character => no value => no value

我希望避免保存像&copy;这样的内容。其中一些数据将以纯文本形式存储。

PHP是否编译为Unicode/MB?此外,json_encode在Unicode/MB上是否能正常工作? - user166390
4
许多Unicode字符没有ASCII等价物 - user166390
这篇文章https://dev59.com/VW025IYBdhLWcg3wW0oc似乎有一个解决方案,尽管它并不让我感到是“正确”的解决方案。它似乎确实需要UTF-8,否则可能会*悄悄地导致null* https://dev59.com/A3I-5IYBdhLWcg3wMFa0和http://stackoverflow.com/questions/7938387/json-encode-php-result-is-null(另一个失败的设计选择:-/) - user166390
3个回答

12

在将数据传递给json_encode函数之前,使用UTF-8格式对数据进行编码。

<?
    $array['copyright_str'] = utf8_encode("Copyright site.com © 2011-2012");
    echo json_encode($array);
?>

2
+1,然而这假设您将所有数据存储和处理为ISO-8859-1,这意味着您的应用程序不支持该编码之外的Unicode字符。从长远来看,完全迁移到UTF-8更好。 - bobince
在这种情况下,您可以使用mb_detect_encoding检查当前数据的格式,然后使用mb_convert_encoding将其转换为UTF-8。 - Saket Patel
2
嗯...请记住,mb_detect_encoding仅仅是一个近似猜测,很容易出错,所以是的。 - bobince

3

我正在使用大量UTF-8符号对数据进行编码,使用的工具是

json_encode($return, JSON_UNESCAPED_UNICODE)

它工作得很好。我用它来编码各种语言:阿拉伯语,中文,泰语,立陶宛语,德语,法语,西班牙语等。所有这些语言都有不同的独特符号。哦,我还没有尝试过编码雪人 ☃ :)


-5

json_encode之前使用urlencode

<?
$array['copyright_str'] = "Copyright site.com © 2011-2012";
$array['copyright_str'] = urlencode($array['copyright_str']);
echo json_encode($array);
?>

4
为什么?这不是一个 URL。那将会"改变数据"并要求使用者进行反向操作。 - user166390
但它会转义版权符号并将其转换为 &copy;。反转是微不足道的。 - Ayush
这不是问题或解决方案。想象一下如果是另一个Unicode字符(比如☃,一个雪人),那么它会被如何处理?如果这只是一个偶然的、hacky的、边缘情况,显然它是不可靠的(除非PHP恰好存在一个仅影响版权符号的Unicode字符的bug)。 - user166390
我想避免在数据库中存储URLENCODED数据,因为如果需要,我无法直接通过phpmyadmin进行编辑。 - user974896
@xbonez — 它不会将其存储为&copy;,那是HTML编码。JSON格式有自己存储字符的方式,没有必要嵌套不同的数据格式。 - Quentin
1
只有在想要将数据作为URL传递时,才使用此格式进行编码,而不是将其保存到数据库中。 - Saket Patel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接