如何在 PHP 中将 JSON 数组保持“每行一个对象”的可读格式重新序列化

12次阅读

如何在 PHP 中将 JSON 数组保持“每行一个对象”的可读格式重新序列化

本文介绍一种绕过标准 `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 格式,并将格式化职责交给专用工具或前端渲染层。

text=ZqhQzanResources