
本文介绍一种绕过标准 `json_encode()` 默认紧凑格式的方法,通过手动拼接实现类似原始输入的“换行分隔、缩进一致”的 json 数组输出风格,适用于调试或特定格式兼容场景。
在 PHP 中,默认的 json_encode() 会将整个 JSON 数据压缩为单行(如 [{"id":"1","name":"john"},...]),而开发过程中常需保留类似原始编辑时的“多行、每对象一行、无额外缩进”的可读格式(即:[\n{"id": "1", ...},\n{"id": "2", ...}\n])。这种格式虽非标准 JSON 规范所强制要求,但在日志记录、配置文件生成或与某些遗留工具交互时仍具实用价值。
关键在于:不依赖 JSON_PRETTY_PRINT(它会添加缩进和嵌套换行,导致结构混乱),而是对已解码的数组逐项 json_encode() 后手动用换行符连接。以下是推荐实现:
// PHP < 8.1 兼容:判断是否为索引列表(非关联数组)
if (!function_exists('array_is_list')) {
function array_is_list(array $a): bool {
return $a === [] || (array_keys($a) === range(0, count($a) - 1));
}
}
/**
* 将索引数组编码为「每对象一行」的 JSON 字符串(无缩进,仅换行分隔)
* 示例输出:[\n{"id":"1","name":"john"},\n{"id":"2","name":"bill"}\n]
*/
function json_encode_oneline_per_item(array $data): string {
if (!array_is_list($data)) {
throw new InvalidArgumentException('Input must be a sequential (non-associative) array');
}
$encodedItems = array_map(fn($item) => json_encode($item, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), $data);
return "[\n" . implode(",\n", $encodedItems) . "\n]";
}
// 使用示例
$json_text = '
[
{"id": "1", "name": "john", "bd": []},
{"id": "2", "name": "gary", "bd": [1, 2]}
]';
$data = json_decode($json_text, true);
// 修改数据(如更新姓名)
$data[1]['name'] = 'bill';
// 重新生成目标格式
$formattedJson = json_encode_oneline_per_item($data);
echo $formattedJson;✅ 输出效果:
[
{"id":"1","name":"john","bd":[]},
{"id":"2","name":"bill","bd":[1,2]}
]⚠️ 注意事项:
立即学习“PHP免费学习笔记(深入)”;
- 此格式不等价于 JSON_PRETTY_PRINT —— 它不处理嵌套对象/数组的缩进,仅保证顶层对象独占一行;
- json_encode() 默认会对中文、斜杠等转义,我们通过 JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES 保持原始可读性;
- 切勿用于生产环境的数据交换:标准 JSON 解析器均能正确处理该格式,但人为干预序列化逻辑易引入歧义,应优先使用标准格式 + 外部工具(如 jq '.' file.json)做可视化美化;
- 若输入含关联数组(键名非数字连续),函数将抛出异常,确保数据结构可控。
总结:该方案是权衡可读性与实现简易性的折中选择,核心思想是「解码 → 变更 → 单项编码 → 手动组装」。真正健壮的工程实践,仍是坚持标准 JSON 格式,并将格式化职责交给专用工具或前端渲染层。











