
本文讲解如何将一组独立的 json 字符串(如 `[]byte` 或 `json.rawmessage`)正确拼接成一个符合标准的 json 数组,避免出现无分隔、无方括号包裹等非法格式问题。
在 Go 中,当需要将多个 JSON 对象(例如 json.RawMessage 类型切片)合并输出为一个合法的 JSON 数组时,不能简单地逐个写入 bytes.Buffer 并期望自动添加逗号和方括号——这正是原始代码的问题所在:它输出的是多个紧挨着的 JSON 对象(如 {...}{...}),这在 JSON 规范中是非法的,无法被标准解析器识别。
正确的做法是手动构造 JSON 数组结构:以 [ 开头,每个对象间用 , 分隔,最后以 ] 结尾。以下是推荐的实现方式:
var buff bytes.Buffer
buff.WriteByte('[') // 开始数组
for i, raw := range sliceOfJsonRawMessages {
if i > 0 {
buff.WriteByte(',') // 非首项前加逗号
}
// 直接写入已校验有效的 JSON 字节(无需再 Compact,除非原始数据含空格/换行)
buff.Write(raw)
}
buff.WriteByte(']') // 结束数组
// 可选:美化或压缩输出
var output bytes.Buffer
err := json.Compact(&output, buff.Bytes()) // 压缩为紧凑格式
// 或使用:err := json.Indent(&output, buff.Bytes(), "", " ") // 美化缩进
if err != nil {
http.Error(w, "JSON formatting error", http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.Write(output.Bytes())⚠️ 关键注意事项:
- 确保 sliceOfJsonRawMessages 中每个元素都是语法合法且已编码完成的 JSON 字节序列(如由 json.Marshal 或 json.RawMessage 提供),否则手动拼接会生成无效 JSON;
- 不要对每个 raw 重复调用 json.Compact(buffer, raw) —— 这会导致嵌套写入、破坏结构;Compact 应仅作用于最终拼好的完整字节数组;
- 若原始数据来自不可信来源,需先验证其 JSON 合法性(例如用 json.Valid(raw)),防止注入非法内容;
- 如需支持流式大数组,可考虑使用 json.Encoder 配合自定义 io.Writer 实现更内存友好的方案(但本例中手动拼接简洁高效,适合中等规模数据)。
通过上述方式,你将得到标准的 JSON 数组响应,例如:
[
{"Dir":"/usr/local/go/src/bytes","ImportPath":"bytes",...},
{"Dir":"/usr/local/go/src/errors","ImportPath":"errors",...}
]该格式可被任意标准 JSON 解析器(JavaScript JSON.parse()、Python json.loads() 等)安全消费。










