为什么这个 PHP 调用 json_encode 会默默地失败——无法处理单引号?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9098507/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why is this PHP call to json_encode silently failing - inability to handle single quotes?
提问by rybosome
I have a stdClass
object called $post
that, when dumped via print_r()
, returns the following:
我有一个stdClass
名为的对象$post
,当通过 转储时print_r()
,返回以下内容:
stdClass Object (
[ID] => 12981
[post_title] => Alumnus' Dinner Coming Soon
[post_parent] => 0
[post_date] => 2012-01-31 12:00:51
)
Echoing the result from calling json_encode()
on this object results in the following:
对调用json_encode()
此对象的结果进行回显会导致以下结果:
{
"ID": "12981",
"post_title": null,
"post_parent": "0",
"post_date": "2012-01-31 12:00:51"
}
I'm assuming that something with the single quote is causing json_encode
to choke, but I don't know what format is needed to escape that. Any ideas?
我假设带有单引号的东西会导致json_encode
窒息,但我不知道需要什么格式来逃避它。有任何想法吗?
EDIT: Fixed mismatch in code examples. I'm running PHP version 5.3.8
编辑:修复了代码示例中的不匹配问题。我正在运行 PHP 版本 5.3.8
EDIT2: Directly after encoding the object, I did this:
EDIT2:直接在编码对象后,我这样做了:
echo json_last_error() == JSON_ERROR_UTF8;
This printed 1
, which means that the following error occurred: "Malformed UTF-8 characters, possibly incorrectly encoded". json_last_error()
这打印了1
,这意味着发生了以下错误:“格式错误的 UTF-8 字符,可能编码不正确”。json_last_error()
EDIT3: Calling utf8_decode()
on the post title resulted in the following: "Alumnus? Dinner Coming Soon". This data is being pulled from a MySQL database - the post title in particular is a text field, UTF-8 encoded. Maybe this single-quote is improperly encoded? The thing is, I have a SQL GUI app, and it appears correctly in that.
EDIT3:调用utf8_decode()
帖子标题会导致以下结果:“校友?晚餐即将到来”。该数据是从 MySQL 数据库中提取的 - 特别是帖子标题是一个文本字段,UTF-8 编码。也许这个单引号编码不正确?问题是,我有一个 SQL GUI 应用程序,它在其中正确显示。
回答by Joni
You need to set the connection encoding before executing queries. How this is done depends on the API you are using to connect:
您需要在执行查询之前设置连接编码。这是如何完成的取决于您用于连接的 API:
- call
mysql_set_charset("utf8")
if you use the old, deprecated API. - call
mysqli_set_charset("utf8")
if you use mysqli - add the
charset
parameterto the connection string if you use PDO and PHP >= 5.3.6. In earlier versions you need to executeSET NAMES utf8
.
- 打电话
mysql_set_charset("utf8")
,如果你使用的时候,弃用API。 mysqli_set_charset("utf8")
如果你使用mysqli调用- 如果您使用 PDO 和 PHP >= 5.3.6,请将
charset
参数添加到连接字符串。在早期版本中,您需要执行SET NAMES utf8
.
When you obtain data from MySQL any text will be encoded in "client encoding", which is likely windows-1252if you don't configure it otherwise. The character that is causing your problem is the "curly quote", seen as 92
in the hex dump, which confirms that the mysql client is encoding text in windows-1252.
当您从 MySQL 获取数据时,任何文本都将以“客户端编码”进行编码,如果您不进行其他配置,则可能是windows-1252。导致您的问题的字符是“卷曲引号”,如92
十六进制转储中所示,它确认 mysql 客户端正在对 windows-1252 中的文本进行编码。
Another thing you might consider is pass all text through utf8_encode
, but in this case it wouldn't produce the correct result. PHP's utf8_encode
converts iso-8859-1-encoded text. In this encoding \x92 is a non-printable control character, which would be converted into a non-printable control character in utf-8. You could use str_replace("\x92", "'", $input)
to fix the problem for this particular character, but if there's any chance there will be any other non-ascii characters in the database you'll want to have the client use UTF-8.
您可能会考虑的另一件事是通过 传递所有文本utf8_encode
,但在这种情况下,它不会产生正确的结果。PHPutf8_encode
转换iso-8859-1编码的文本。在这种编码中,\x92 是一个不可打印的控制字符,它将被转换为 utf-8 中的一个不可打印的控制字符。您可以使用str_replace("\x92", "'", $input)
此特定字符来修复问题,但如果有可能数据库中存在任何其他非 ascii 字符,您将希望客户端使用 UTF-8。
回答by Umbrella
What I've had to do in the past to json_encode on text with utf8 characters is
过去我必须对带有 utf8 字符的文本进行 json_encode 的操作是
json_encode( utf8_encode( $s ) );
and in some cases
在某些情况下
json_encode( htmlspecialchars( utf8_encode( $s ) ) );
the utf8_encode() to handle special characters (note, that's Encode, not Decode)
utf8_encode() 处理特殊字符(注意,这是编码,不是解码)
the htmlspecialchars() depending on how you mean to use the JSON string, you may be able to leave this out
htmlspecialchars() 取决于您打算如何使用 JSON 字符串,您可以将其省略
and finally, json_encode() to get your JSON packet.
最后, json_encode() 获取您的 JSON 数据包。
Since you want to json_encode an object, you would need to call utf8_encode() on each text part first, or write a simple recursive utf8_encode(). For your example case, this would do:
由于您想对对象进行 json_encode,您需要先对每个文本部分调用 utf8_encode(),或者编写一个简单的递归 utf8_encode()。对于您的示例案例,这将执行以下操作:
function myEncode($o) {
$o->title = utf8_encode($o->title);
return json_encode($o);
}
回答by Jhollman
i was having the same issue while JSON encoding a php array from an ODBC query results, my Server's OBC is configured with 'en_US.819', is a production server so there is no way i can even touch that!!.
我在 JSON 编码来自 ODBC 查询结果的 php 数组时遇到了同样的问题,我的服务器的 OBC 配置为“en_US.819”,是一个生产服务器,所以我什至无法触摸它!!
when i tried:
当我尝试:
echo json_encode($GLOBALS['response'], true);
Where 'respose' is an array with the results, it works as intended as long no bizarre char is present, if so, json_encode fails returning empty.
其中 'respose' 是一个带有结果的数组,只要不存在奇怪的字符,它就会按预期工作,如果是这样,json_encode 将失败返回空。
The solution?.... UTF encode results while fetching the rows from query:
解决方案?....从查询中获取行时对结果进行 UTF 编码:
$result = odbc_exec($conn, $sql_query);
$response = array();
while( $row = odbc_fetch_array($result) ) {
$json['pers_identificador'] = $row['pers_identificador'];
$json['nombre_persona'] = utf8_encode( $row['nombre_persona'] );
$json['nombre_1'] = utf8_encode($row['nombre_1'] );
$json['nombre_2'] = utf8_encode($row['nombre_2'] );
array_push($response, $json);
}
Now json_encode works!!!, the resulting string is something like this:
现在 json_encode 工作了!!!,结果字符串是这样的:
{"page_id":300,"max_rows":"100","cant_rows":"12897","datos":
[{"pers_identificador":"301","cedula":"15250068","interno_1":"178202","interno_2":"","nombre_persona":"JOSE JUAN PANDOLFO ZAGORODKO","nombre_1":"JOSE","nombre_2":"JUAN",....
That fixed my issue.
那解决了我的问题。
回答by manish1706
I would like to refer you about this issue, on linkI suggest you use a json_encode wrapper like this :
我想向您介绍这个问题,在链接上我建议您使用这样的 json_encode 包装器:
function safe_json_encode($value){
if (version_compare(PHP_VERSION, '5.4.0') >= 0) {
$encoded = json_encode($value, JSON_PRETTY_PRINT);
} else {
$encoded = json_encode($value);
}
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);
return safe_json_encode($clean);
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;
}
And after define these function you can use it direct,
定义好这些函数后就可以直接使用了,
echo safe_json_encode($response);
回答by Valentina Ungurean
You can try to set the charset in the database config:
您可以尝试在数据库配置中设置字符集:
'charset' => 'utf8',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
)