
本文介绍一种在 php 中手动构造“类原始风格”json 字符串的方法,使其维持 `[` 开头、每个对象独占一行、末尾带 `]` 的可读格式,而非默认的单行紧凑输出。适用于调试或特定格式兼容场景,但不推荐用于生产环境。
在 PHP 中,json_encode() 默认生成紧凑、无换行、无空格的 JSON 字符串(如 [{“id”:”1″,”name”:”john”},…]),这虽利于传输与解析,却不便于人工阅读或版本控制比对。而用户原始 JSON 文件采用的是“类手工排版”风格:数组整体换行包裹,每个对象独立成行、字段间保留空格(如 “id”: “1” 而非 “id”:”1″)。这种格式虽非标准 JSON 规范所强制要求,但在某些编辑场景(如 Git diff 友好、配置文件维护)中确有实用价值。
要实现该效果,不能依赖 json_encode() 的内置选项(如 JSON_PRETTY_PRINT 会产生缩进嵌套,不符合“每对象一行”的扁平结构),而需手动拼接:
- 确保输入为索引数组(list):使用 array_is_list()(PHP ≥8.1)或自定义 polyfill 判断,避免关联数组导致逻辑错误;
- 逐项 json_encode() 每个元素:利用其默认紧凑格式保证单个对象内无额外换行;
- 用 implode(“,/n”, …) 连接对象:实现逗号+换行分隔;
- 手动包裹 [ 和 ] 并添加首尾换行:达成目标结构。
以下是完整、可直接运行的示例代码:
// PHP < 8.1 兼容 polyfill
if (!function_exists('array_is_list')) {
function array_is_list(array $a): bool {
return $a === [] || (array_keys($a) === range(0, count($a) - 1));
}
}
function formatJsonAsOneLinePerItem(array $data): string {
if (!array_is_list($data)) {
throw new InvalidArgumentException('Input must be a sequential array (list).');
}
$encodedItems = array_map(fn($item) => json_encode($item), $data);
return "[/n" . implode(",/n", $encodedItems) . "/n]";
}
// 示例使用
$json_text = '
[
{"id": "1", "name": "john", "bd": []},
{"id": "2", "name": "gary", "bd": [1, 2]}
]';
$decoded = json_decode($json_text, true);
// 修改数据(如更新姓名)
$decoded[1]['name'] = 'bill';
// 重新格式化为原始风格
$result = formatJsonAsOneLinePerItem($decoded);
echo $result;
输出结果严格匹配需求:
立即学习“PHP免费学习笔记(深入)”;
[
{"id":"1","name":"john","bd":[]},
{"id":"2","name":"bill","bd":[1,2]}
]
⚠️ 重要注意事项:
- 此方法生成的 JSON 完全合法(符合 RFC 8259),空格与换行在 JSON 中是允许的空白字符,不影响解析;
- 但它牺牲了可维护性与健壮性:一旦数据结构嵌套加深(如 bd 内含对象),手动拼接将迅速失控;
- 强烈建议替代方案:
总之,该技巧是特定场景下的“权宜之计”,理解其原理有助于规避误用,而拥抱标准工具链才是长期高效之道。
