Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PHP json_decode error: Control character error, possibly incorrectly encoded #43

Open
yankewei opened this issue Jul 17, 2024 · 0 comments
Labels
PHP 有关 PHP 语言的

Comments

@yankewei
Copy link
Owner

PHP 在进行 json 解析的时候会有很多报错,如果解析失败,可以使用json_last_error_msg方法,它会返回一个解析失败的原因。原因之一就有一个JSON_ERROR_CTRL_CHAR,表示Control character error, possibly incorrectly encoded,提示有可能 JSON 对象中包含了控制字符串。下面是一个例子:

	{	"hello":
"	world"
}

看不出来,可以复制这段文本,使用 vim 打开,然后设置显示隐藏字符,可以在命令模式下,输入:set list,可以看到如下的字符, ^I表示制表字符,$ 表示换行符

^I{^I"hello":^I$
"^Iworld"$
}$

什么是控制字符

可以通过这个 ASCII CODE 看一下 control character 都包含哪些字符,很明显制表符和换行符都属于 control character。

JSON 规范

那上边的 JSON 中开头和字符串中都包含控制字符,到底是哪个导致的。需要我们看看 JSON 的规范。RFC8259

开头和结尾

其中对 JSON 做了明确的规范,表明开头和结尾都可以包含空白字符,所以我们把开头的制表符和结尾的换行符去掉后仍然无法解析或者说他们并不影响我们的解析。

字符串

规范还对字符串 string 做了声明

A string begins and ends with
quotation marks. All Unicode characters may be placed within the
quotation marks, except for the characters that MUST be escaped:
quotation mark, reverse solidus, and the control characters (U+0000
through U+001F).

可以看到,所有的字符必需被引号包裹,并且强调引号反斜线, 控制字符需要被转义,这也是导致我们无法解析的原因。

解决办法

既然是因为字符串中包含了控制字符,我们可以根据规范中提到的控制字符范围,把这些字符替换掉。如果我们把它们转义那么开头的字符就会被转义成\t,但是规范要求开头必需是空白字符,所以只能转义字符串内部的控制字符。如果可以不需要控制字符的可以直接替换成空字符:

$json_string = preg_replace('/[\x00-\x1F\x80-\x9F]/u', '', $json_string);
@yankewei yankewei added PHP 有关 PHP 语言的 CSS Go 有关Go语言的 and removed CSS Go 有关Go语言的 labels Aug 7, 2024
@yankewei yankewei added PHP 有关 PHP 语言的 and removed PHP 有关 PHP 语言的 labels Aug 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
PHP 有关 PHP 语言的
Projects
None yet
Development

No branches or pull requests

1 participant