为什么这个 PHP 调用json_encode静默地失败 - 无法处理单引号?

2022-08-30 11:20:16

我有一个名为的对象,当通过 转储时,返回以下内容:stdClass$postprint_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;

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

编辑3:呼吁帖子标题导致以下内容:“校友?晚餐即将到来”。这些数据是从MySQL数据库中提取的 - 特别是帖子标题是一个文本字段,UTF-8编码。也许这个单引号编码不正确?问题是,我有一个SQL GUI应用程序,它在其中正确显示。utf8_decode()


答案 1

在执行查询之前,您需要设置连接编码。如何完成此操作取决于您用于连接的 API:

  • 调用(如果使用旧的、已弃用的 API)。mysql_set_charset("utf8")
  • 调用,如果你使用 mysqlimysqli_set_charset("utf8")
  • 如果使用 PDO 和 PHP >= 5.3.6,则将字符集参数添加到连接字符串中。在早期版本中,您需要执行 。SET NAMES utf8

当您从MySQL获取数据时,任何文本都将以“客户端编码”进行编码,如果您不以其他方式进行配置,则可能是windows-1252。导致问题的字符是“卷曲引号”,类似于十六进制转储,它确认mysql客户端正在windows-1252中编码文本。92

您可能考虑的另一件事是传递所有文本,但在这种情况下,它不会产生正确的结果。PHP 的转换 iso-8859-1 编码文本。在此编码中,\x92 是不可打印的控制字符,它将在 utf-8 中转换为不可打印的控制字符。您可以使用 来修复此特定字符的问题,但如果数据库中有可能存在任何其他非 ascii 字符,则需要让客户端使用 UTF-8。utf8_encodeutf8_encodestr_replace("\x92", "'", $input)


答案 2

我过去不得不做的是,用utf8字符json_encode文本

json_encode( utf8_encode( $s ) );

在某些情况下

json_encode( htmlspecialchars( utf8_encode( $s ) ) );

utf8_encode() 来处理特殊字符(注意,这是编码,而不是解码)

htmlspecialchars() 取决于您打算如何使用 JSON 字符串,您可以省略它

最后,json_encode() 获取 JSON 数据包。

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

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

推荐