加了json_unescaped_unicode就输出“你好”,不加则输出"\u4f60\u597d";返回null是因数据非utf-8或含非法字符,与flag无关。

json_encode 输出中文是 \u4f60\u597d 还是“你好”,只看 flag 不看版本
PHP 7.4 和 7.3、7.2 甚至 5.4 在 JSON_UNESCAPED_UNICODE 行为上完全一致:加了就输出明文中文,不加就转成 \u4f60\u597d。所谓“7.4 变了”基本是误判——你看到的差异,大概率来自环境配置不统一,比如开发机开了 flag、测试机没开,或者前端没设 Content-Type: application/json; charset=utf-8 导致浏览器用 GBK 解码 UTF-8 字节流。
为什么加了 JSON_UNESCAPED_UNICODE 还返回 null?不是 flag 的问题,是数据本身坏了
json_encode() 返回 null(或 false)时,JSON_UNESCAPED_UNICODE 完全无关。真正原因几乎全是编码污染或非法类型:
- 数据库连接没设
utf8mb4,查出的字段含 GBK 字节 - 从文件读取时带 BOM 或混入了
\r\n控制字符,var_dump()看不出但json_last_error_msg()会报"Malformed UTF-8 characters, possibly incorrectly encoded" - 数组里塞进了
mysqli资源、未关闭的句柄,或对象存在递归引用 - 表单 POST 数据没经
mb_convert_encoding($str, 'UTF-8', 'auto')清洗,原始编码可能是 GB2312
验证方式极简单:var_dump(json_last_error_msg()) —— 错误信息比猜版本靠谱十倍。
安全又省心的 json_encode 调用写法
别只靠 JSON_UNESCAPED_UNICODE。组合几个关键 flag 才算兜底:
-
JSON_UNESCAPED_UNICODE:保留中文可读性 -
JSON_UNESCAPED_SLASHES:避免\/转义,防止嵌入 HTML 属性时被截断 -
JSON_INVALID_UTF8_SUBSTITUTE(PHP 7.2+):把非法 UTF-8 字节替换成,而不是让整个编码失败
示例:$json = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_INVALID_UTF8_SUBSTITUTE);
若仍返回 false,说明数据源头有硬伤——得回溯清洗,不是调参能解决的。
最容易被忽略的隐形坑:字符串里的 \n、\r、\0 和零宽空格
你看到 JSON 输出里某条标题是 "PHP\nTutorial",那不是 json_encode 加的换行,而是原始字符串里真有 \n。这类控制字符在 var_dump 里不显眼,但会导致 JSON 无效(尤其当值被拼进 data-json='...' 属性时)。解决方法不是改 flag,而是预处理:
- 用
preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/u', '', $str)清掉不可见控制符 - 对用户输入字段,用
trim()+str_replace(["\r\n", "\r", "\n"], ' ', $str)统一空白符 - 检查是否含零宽空格(
\xE2\x80\x8B),它在编辑器里完全不可见,却会让 JSON 解析失败
这些字符不会触发 json_last_error(),但会让前端 JSON.parse() 报错——问题不在 PHP 编码逻辑,而在数据进入 json_encode 前就已携带杂质。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











