
本文详解 Go 语言中处理服务器返回 JSON 数组的完整流程,重点解决因结构体与 JSON 格式不匹配(如误将数组当作单个对象解码)导致的 json.Unmarshal 错误,并提供可直接运行的代码示例、字段命名规范及健壮性建议。
本文详解 go 语言中处理服务器返回 json 数组的完整流程,重点解决因结构体与 json 格式不匹配(如误将数组当作单个对象解码)导致的 `json.unmarshal` 错误,并提供可直接运行的代码示例、字段命名规范及健壮性建议。
在 Go 中调用 HTTP POST 接口后,若服务端返回的是 JSON 数组(例如 [{"n_expediente":"9","enviar":"2"}]),而客户端仍按单个对象方式定义结构体并解码(如 var re ResponseFromPost),就会触发 json: cannot unmarshal array into Go value 类型错误——你看到的 &{%!e(string=array)...} 实际是 fmt.Println 对未成功解码的零值结构体的异常格式化输出,根源在于类型不匹配。
✅ 正确做法:使用切片(slice)接收 JSON 数组
Go 的 json.Unmarshal 要求目标变量类型必须与 JSON 数据结构严格对应。对于数组响应,应声明为结构体切片:
type ResponseItem struct {
NExpediente string `json:"n_expediente"` // 驼峰命名 + json tag 映射下划线字段
Enviar string `json:"enviar"`
}
func main() {
// ... 构造 client 和 req(略)
res, err := client.Do(req)
if err != nil {
log.Fatal("HTTP request failed:", err)
}
defer res.Body.Close()
body, err := io.ReadAll(res.Body) // 替换已弃用的 ioutil.ReadAll
if err != nil {
log.Fatal("Failed to read response body:", err)
}
var responses []ResponseItem // 关键:声明为切片,而非单个结构体
if err := json.Unmarshal(body, &responses); err != nil {
log.Fatal("JSON decode failed:", err)
}
// 安全访问:检查切片长度后再取值
if len(responses) > 0 {
fmt.Println("First item enviar:", responses[0].Enviar)
}
// 遍历所有结果(推荐方式)
for i, item := range responses {
fmt.Printf("Item %d: n_expediente=%s, enviar=%s\n", i+1, item.NExpediente, item.Enviar)
}
}⚠️ 关键注意事项
- JSON Tag 不可省略:Go 结构体字段名默认按首字母大写导出,但 JSON 字段为小写下划线风格(如 "n_expediente")。必须通过 json:"n_expediente" 显式映射,否则解码失败且无报错(字段保持零值)。
- 避免命名歧义:原结构体名 ResponseFromPost 易被误解为单个响应,建议改为 ResponseItem 或 PostResponse,并明确其为数组元素类型。
- 错误处理需分层:HTTP 错误(res.StatusCode != 200)、IO 错误(读取 Body 失败)、JSON 解析错误(Unmarshal 失败)应分别校验,不可仅依赖单一 err。
- 内存安全:io.ReadAll 会将整个响应体加载到内存,对大响应需考虑流式解析(如 json.Decoder),但本例中小数据量适用。
✅ 总结
当服务端返回 JSON 数组时,Go 客户端必须使用 []YourStruct 切片类型配合 json.Unmarshal,并确保结构体字段通过 json tag 准确映射原始字段名。辅以完善的错误检查与遍历逻辑,即可稳定、清晰地提取所有数据项。










