Skip to content

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);
}

注意事项

  1. 资源类型无法编码:数据库连接、文件句柄等资源不能 JSON 化
  2. 循环引用:对象循环引用会导致编码失败
  3. 空数组 vs 空对象json_encode([])[]json_encode(new stdClass()){}
  4. 数值键名:数组的数值键名会被转为字符串
php
// 强制空数组输出为对象
$empty = new stdClass();
echo json_encode($empty);  // {}

// 或者使用选项
echo json_encode([], JSON_FORCE_OBJECT);  // {}

Binstork