JSON 处理常见问题
JSON 是前后端数据交互的主要格式。本文介绍 PHP 中 JSON 处理的常见问题及解决方案。
基础使用
php
// 编码(数组/对象转 JSON)
$data = ['name' => '张三', 'age' => 25];
$json = json_encode($data, JSON_UNESCAPED_UNICODE);
echo $json; // {"name":"张三","age":25}
// 解码(JSON 转数组/对象)
$array = json_decode($json, true); // 返回数组
$object = json_decode($json, false); // 返回对象(默认)中文字符处理
php
$data = ['message' => '你好世界'];
// 默认输出 Unicode 编码
echo json_encode($data);
// 输出:{"message":"你好世界"}
// 保留中文字符
echo json_encode($data, JSON_UNESCAPED_UNICODE);
// 输出:{"message":"你好世界"}
// 常用选项组合
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);处理大数字精度丢失
php
// 问题:JS 最大安全整数是 2^53-1,超过会精度丢失
$id = 9223372036854775807; // 64位整数
echo json_encode(['id' => $id]);
// 输出:{"id":9223372036854775807} - 可能被 JS 解析错误
// 解决方案:转为字符串
$safeData = [
'id' => (string)$id,
'id_raw' => $id // 原始值给后端使用
];
echo json_encode($safeData, JSON_UNESCAPED_UNICODE);
// 或使用 JSON_BIGINT_AS_STRING(PHP 7.0+)
$json = '{"id":9223372036854775807}';
$data = json_decode($json, true, 512, JSON_BIGINT_AS_STRING);
echo $data['id']; // 字符串:9223372036854775807错误处理
php
function jsonEncodeSafe($data) {
$json = json_encode($data);
if ($json === false) {
$error = json_last_error_msg();
error_log("JSON encode error: $error");
return null;
}
return $json;
}
function jsonDecodeSafe($json, $assoc = true) {
$data = json_decode($json, $assoc);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new Exception('JSON parse error: ' . json_last_error_msg());
}
return $data;
}
// 常见错误类型
const JSON_ERRORS = [
JSON_ERROR_NONE => '无错误',
JSON_ERROR_DEPTH => '超出最大堆栈深度',
JSON_ERROR_STATE_MISMATCH => '无效的 JSON 状态',
JSON_ERROR_CTRL_CHAR => '控制字符错误',
JSON_ERROR_SYNTAX => '语法错误',
JSON_ERROR_UTF8 => 'UTF-8 编码错误',
JSON_ERROR_RECURSION => '递归错误',
JSON_ERROR_INF_OR_NAN => '包含 INF 或 NAN',
JSON_ERROR_UNSUPPORTED_TYPE => '不支持的类型',
];处理特殊字符和换行
php
// 处理内容中的换行符
$content = "第一行\n第二行\n第三行";
$safeContent = str_replace(["\r\n", "\r", "\n"], '\\n', $content);
// HTML 实体处理
$html = "<p>包含 HTML 的内容</p>";
$json = json_encode($html, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT);
// 更安全的输出(防止 XSS)
function jsonEncodeForHtml($data) {
return json_encode($data, JSON_HEX_TAG | JSON_HEX_AMP |
JSON_HEX_APOS | JSON_HEX_QUOT | JSON_UNESCAPED_UNICODE);
}
// 在 JS 中使用
// var data = <?php echo jsonEncodeForHtml($data); ?>;遍历解析 JSON 数组
php
$jsonArray = '[{"id":1},{"id":2},{"id":3}]';
// 逐条处理大数组(内存友好)
$stream = fopen('php://memory', 'rw');
fwrite($stream, $jsonArray);
rewind($stream);
$decoder = new JsonMachine\JsonMachine($stream, '');
foreach ($decoder as $item) {
processItem($item);
}
// 或使用 json_decode 后遍历(适合小数组)
$items = json_decode($jsonArray, true);
foreach ($items as $item) {
processItem($item);
}注意事项
- 资源类型无法编码:数据库连接、文件句柄等资源不能 JSON 化
- 循环引用:对象循环引用会导致编码失败
- 空数组 vs 空对象:
json_encode([])是[],json_encode(new stdClass())是{} - 数值键名:数组的数值键名会被转为字符串
php
// 强制空数组输出为对象
$empty = new stdClass();
echo json_encode($empty); // {}
// 或者使用选项
echo json_encode([], JSON_FORCE_OBJECT); // {}