本文详解如何在go中正确读取包含多个json对象的数组文件,将其解析为可遍历结构,并逐一序列化为原始json字节流发送至rest端点,避免类型断言错误与内存冗余。
在Go中处理JSON数组(尤其是顶层为 []object 的文件)时,常见误区是预先定义强类型结构体——当字段动态、嵌套复杂或仅需透传原始JSON时,反而增加维护成本且易因字段缺失/类型不匹配导致解析失败。更灵活、可靠的方式是采用 interface{} + 类型断言进行泛型解析,再用 json.Marshal 将每个元素还原为独立JSON字节流,直接用于HTTP请求。
以下是一个生产就绪的完整示例,涵盖文件读取、安全解析、逐对象序列化及错误处理:
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"time"
)
func main() {
// 1. 读取JSON数组文件
data, err := ioutil.ReadFile("dat_one_extract.json")
if err != nil {
log.Fatalf("读取文件失败: %v", err)
}
// 2. 解析为顶层接口切片 []interface{}
var jsonArray []interface{}
if err := json.Unmarshal(data, &jsonArray); err != nil {
log.Fatalf("JSON解析失败: %v", err)
}
// 3. 遍历每个JSON对象,序列化后发送至REST端点
endpoint := "https://api.example.com/ingest"
client := &http.Client{Timeout: 30 * time.Second}
for i, item := range jsonArray {
// 将单个对象重新编码为JSON字节(保持原始结构与格式)
jsonBytes, err := json.Marshal(item)
if err != nil {
log.Printf("第 %d 项序列化失败: %v", i+1, err)
continue
}
// 4. 构造HTTP POST请求(Content-Type: application/json)
req, err := http.NewRequest("POST", endpoint, bytes.NewReader(jsonBytes))
if err != nil {
log.Printf("第 %d 项构建请求失败: %v", i+1, err)
continue
}
req.Header.Set("Content-Type", "application/json")
// 5. 发送请求
resp, err := client.Do(req)
if err != nil {
log.Printf("第 %d 项发送失败: %v", i+1, err)
continue
}
defer resp.Body.Close()
if resp.StatusCode = 300 {
log.Printf("第 %d 项接收非成功状态码: %d", i+1, resp.StatusCode)
continue
}
fmt.Printf("✅ 第 %d 项已成功发送\n", i+1)
}
}
⚠️ 关键注意事项: