为什么这个PHP调用json_encode默默无闻 – 无法处理单引号?
我有一个名为$post
的stdClass
对象,当通过print_r()
转储时,返回以下内容:
stdClass Object ( [ID] => 12981 [post_title] => Alumnus' Dinner Coming Soon [post_parent] => 0 [post_date] => 2012-01-31 12:00:51 )
在此对象上调用json_encode()
结果会导致以下结果:
{ "ID": "12981", "post_title": null, "post_parent": "0", "post_date": "2012-01-31 12:00:51" }
我假设单引号的东西导致json_encode
呛,但我不知道需要什么格式来逃避。 有任何想法吗?
编辑:修正代码示例中的不匹配。 我正在运行PHP版本5.3.8
编辑2:直接编码对象后,我做到了这一点:
echo json_last_error() == JSON_ERROR_UTF8;
这打印1
,这意味着发生以下错误:“格式错误的UTF-8字符,可能错误编码”。 json_last_error()
编辑3:在post标题上调用utf8_decode()
导致以下结果:“校友?晚餐即将来临”。 这些数据是从MySQL数据库中提取的,特别是文章标题是UTF-8编码的文本字段。 也许这个单引号是不正确的编码? 事情是,我有一个SQLgraphics用户界面的应用程序,它看起来是正确的。
在执行查询之前,您需要设置连接编码。 这是如何完成取决于你用来连接的API:
- 调用
mysql_set_charset("utf8")
如果您使用旧的,弃用的API 。 - 如果使用mysqli,请调用
mysqli_set_charset("utf8")
- 如果使用PDO和PHP> = 5.3.6,则将
charset
参数添加到连接string中。 在早期版本中,您需要执行SET NAMES utf8
。
当你从MySQL获取数据时,任何文本都将被编码为“客户端编码”,如果没有configuration,这可能是windows-1252 。 导致你的问题的字符是“卷发报价”,在hex转储中被看作是92
,这确认了mysql客户端正在windows-1252中编码文本。
你可能会考虑的另一件事是通过utf8_encode
所有文本,但在这种情况下,它不会产生正确的结果。 PHP的utf8_encode
转换iso-8859-1编码的文本。 在这种编码中,\ x92是一个不可打印的控制字符,它将在utf-8中被转换成一个不可打印的控制字符。 你可以使用str_replace("\x92", "'", $input)
来解决这个特定字符的问题,但是如果有任何机会,在数据库中会有其他非ascii字符,客户端使用UTF-8。
我过去必须做的,以utf8字符文本json_encode是
json_encode( utf8_encode( $s ) );
在某些情况下
json_encode( htmlspecialchars( utf8_encode( $s ) ) );
utf8_encode()来处理特殊字符(注意,这是编码,而不是解码)
htmlspecialchars()取决于你的意思是如何使用JSONstring,你可能会离开这个
最后,用json_encode()来获取你的JSON包。
既然你想json_encode一个对象,你需要先在每个文本部分调用utf8_encode(),或者编写一个简单的recursion的utf8_encode()。 对于你的例子,这将做到:
function myEncode($o) { $o->title = utf8_encode($o->title); return json_encode($o); }
我有同样的问题,而JSON从ODBC查询结果编码一个PHP数组,我的服务器的OBCconfiguration了'en_US.819',是一个生产服务器,所以我没有办法,甚至可以触摸!
当我尝试:
echo json_encode($GLOBALS['response'], true);
其中'respose'是一个包含结果的数组,如果没有奇怪的字符存在,它会按预期工作,如果是这样的话,json_encode将无法返回空。
解决scheme?…. 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); }
现在json_encode工作!!!,结果string是这样的:
{"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",....
这解决了我的问题。
我想引用你关于这个问题的链接,我build议你使用这样的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; }
而定义这些function之后你可以直接使用它,
echo safe_json_encode($response);
您可以尝试在数据库configuration中设置字符集:
'charset' => 'utf8', 'driver_options' => array( PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\'' )