为什么对json_encode的PHP调用失败了——无法处理单引号?

为什么对json_encode的PHP调用失败了——无法处理单引号?,php,json,Php,Json,我有一个名为$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 ) { "ID": "12981", "post_title":

我有一个名为
$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
)
{
    "ID": "12981",
    "post_title": null,
    "post_parent": "0",
    "post_date": "2012-01-31 12:00:51"
}
对该对象调用
json\u encode()
的结果会产生以下结果:

stdClass Object (
    [ID] => 12981
    [post_title] => Alumnus' Dinner Coming Soon
    [post_parent] => 0
    [post_date] => 2012-01-31 12:00:51
)
{
    "ID": "12981",
    "post_title": null,
    "post_parent": "0",
    "post_date": "2012-01-31 12:00:51"
}
我假设单引号导致
json\u encode
阻塞,但我不知道需要什么格式来避免这种情况。有什么想法吗

编辑:修复了代码示例中的不匹配。我正在运行PHP版本5.3.8

EDIT2:在对对象进行编码后,我直接执行了以下操作:

echo json_last_error() == JSON_ERROR_UTF8;
这是打印的
1
,这意味着发生了以下错误:“格式错误的UTF-8字符,可能编码不正确”


编辑3:在帖子标题上调用
utf8\u decode()
,结果是:“校友?晚餐马上就要来了”。这些数据是从MySQL数据库中提取的,特别是文章标题是一个文本字段,UTF-8编码。也许这个单引号的编码不正确?问题是,我有一个SQL GUI应用程序,它在其中正确显示。

在执行查询之前,您需要设置连接编码。如何实现这一点取决于您用于连接的API:

  • 如果使用,请调用mysql\u set\u字符集(“utf8”)
  • 如果使用,请调用mysqli\u set\u字符集(“utf8”)
  • 如果使用PDO和PHP>=5.3.6,则将添加到连接字符串中。在早期版本中,您需要执行
    设置名称utf8
当您从MySQL获取数据时,任何文本都将被编码为“客户机编码”,如果您没有对其进行其他配置,则很可能是这样。导致问题的字符是“卷曲引号”,在十六进制转储中被视为
92
,它确认mysql客户端正在windows-1252中编码文本


另一件事,你可以考虑将所有的文本通过<代码> UTF8YEngEng/<代码>,但是在这种情况下,它不会产生正确的结果。PHP的utf8编码转换iso-8859-1编码文本。在此编码中\x92是一个不可打印的控制字符,它将转换为utf-8中的不可打印控制字符。您可以使用

str_replace(“\x92”,“'”,$input)
来解决此特定字符的问题,但是如果数据库中有任何其他非ascii字符,您将希望客户端使用UTF-8。

我过去必须使用utf8字符对文本进行json_编码的方法是

json_encode( utf8_encode( $s ) );
在某些情况下

json_encode( htmlspecialchars( utf8_encode( $s ) ) );
utf8_encode()用于处理特殊字符(注意,这是编码,不是解码)

htmlspecialchars()根据您打算如何使用JSON字符串,您可以省略此选项

最后,使用json_encode()获取json数据包

由于要对对象进行json_编码,因此需要首先对每个文本部分调用utf8_encode(),或者编写一个简单的递归utf8_encode()。对于您的示例,这将执行以下操作:

function myEncode($o) {
    $o->title = utf8_encode($o->title);
    return json_encode($o);
}

当JSON从ODBC查询结果中编码php数组时,我也遇到了同样的问题,我的服务器的OBC配置为“en_US.819”,是一个生产服务器,所以我根本无法触及它

当我尝试时:

echo json_encode($GLOBALS['response'], true);
其中“respose”是一个带有结果的数组,只要不存在奇怪的字符,它就可以正常工作,若存在,json_encode将无法返回空

解决方案是什么?。。。。从查询中提取行时对结果进行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_编码工作了!!!,结果字符串如下所示:

{"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",....

这解决了我的问题。

我想向您介绍这个问题, 在…上 我建议您使用json_编码包装器,如下所示:

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;
}
在定义了这些函数之后,您可以直接使用它

echo safe_json_encode($response);

您可以尝试在数据库配置中设置字符集:

'charset' => 'utf8',
'driver_options' => array(
    PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
)

... 您正在运行哪个PHP版本?我注意到转储的对象和
json\u encode()
结果不匹配(ID不同)-请验证您的代码示例是否正确。它也适用于我。设置帖子标题时,是否用双引号(“”)括起来?显示该字符串的十六进制转储。416c756d6e7573922044696e6e657220436f6d696e6720536f6f6e@JimD该对象是从MySQL数据库中提取的,
post\u title
字段是一个UTF-8文本字段,或等效的mysqli\u set\u字符集($link,“utf8”)如果您正在使用这些。DBAL使用
字符集
,您也可以将其设置为“utf8”来解决此问题。mysql和mysqli函数不推荐使用,我们使用PDOnow@MarcoMarsala固定的mysqli在寻找
utf8mb4
时没有被弃用,因为mysqli中有两个版本,所以使用
uft8
可能会有所帮助。如果$s是一个数组,那么,我想必须执行类似于
array\u walk\u recursive($s,'utf8\u encode')的操作@umbrane仅供参考,该代码段将$s设置为true。我相信您正在考虑数组映射,不幸的是它没有递归模式足够了。谢谢