
Go 中解析 JSON 时,若结构体字段未导出(首字母小写),encoding/json 无法访问,导致反序列化失败;同时,需正确处理 JSON 数组(如 [{"offset":...}, {...}])而非单个对象。
go 中解析 json 时,若结构体字段未导出(首字母小写),`encoding/json` 无法访问,导致反序列化失败;同时,需正确处理 json 数组(如 `[{"offset":...}, {...}]`)而非单个对象。
在 Go 中使用 encoding/json 解析 JSON 数据是一个高频操作,但新手常因两个关键细节踩坑:结构体字段不可导出 和 JSON 数据格式与目标类型不匹配。你提供的示例中,原始 JSON 是一个对象数组(即以 [ 开头的 JSON 文本),而结构体字段全为小写(如 offset, fcn_addr),这直接导致 json.Unmarshal 返回 invalid character 'o' looking for beginning of object key string 或更常见的 json: cannot unmarshal object into Go value of type ... 错误。
✅ 正确做法:导出字段 + 匹配 JSON 结构
首先,Go 的 encoding/json 包只能访问导出(public)字段——即首字母必须大写。因此,你的结构体必须改为:
type DisassembleOutput struct {
Offset int `json:"offset"`
FcnAddr int `json:"fcn_addr"` // 注意:Go 命名习惯推荐 FcnAddr 而非 Fcn_addr
FcnLast int `json:"fcn_last"`
Size int `json:"size"`
Opcode string `json:"opcode"`
Bytes string `json:"bytes"`
Type string `json:"type,omitempty"` // 可选字段,若 JSON 中可能缺失
TypeNum int `json:"type_num,omitempty"`
Type2Num int `json:"type2_num,omitempty"`
Flags []string `json:"flags,omitempty"`
Comment string `json:"comment,omitempty"`
}
? 提示:json 标签显式指定 JSON 字段名,增强可读性与容错性;omitempty 表示该字段为空值时不参与序列化,也允许反序列化时忽略缺失字段。
✅ 解析 JSON 数组:用切片接收
你提供的 JSON 是一个包含多个对象的数组(注意开头的 [ 和逗号分隔),因此不能直接 Unmarshal 到单个 DisassembleOutput 实例,而应使用切片:
jsonData := []byte(`[
{
"offset": 4224368,
"fcn_addr": 4224368,
"fcn_last": 4224408,
"size": 2,
"opcode": "add byte [rax], al",
"bytes": "0000",
"type": "add",
"type_num": 17,
"type2_num": 0,
"flags": ["entry0", "sym._start"],
"comment": "WzEzXSB2YT0weDAwNDA3NTcwIHBhPTB4MDAwMDc1NzAgc3o9MTA5OTE4NiB2c3o9MTA5OTE4NiByd3g9LXIteCAudGV4dA=="
},
{
"offset": 4224370,
"fcn_addr": 4224368,
"fcn_last": 4224408,
"size": 2,
"opcode": "add byte [rax], al",
"bytes": "0000",
"type": "add",
"type_num": 17,
"type2_num": 0
}
]`)
var outputs []DisassembleOutput
if err := json.Unmarshal(jsonData, &outputs); err != nil {
log.Fatal("JSON 解析失败:", err)
}
fmt.Printf("成功解析 %d 条指令\n", len(outputs))
for i, out := range outputs {
fmt.Printf("[%d] offset=%d, opcode=%q, flags=%v\n", i, out.Offset, out.Opcode, out.Flags)
}
⚠️ 注意事项与最佳实践
- 永远检查 err:json.Unmarshal 失败时不会 panic,但会静默跳过或填充零值,务必校验错误。
- 字段类型要严格匹配:如 JSON 中 "offset": 4224368 是数字,Go 中必须用 int/int64,不能用 string;字符串数组("flags": [...])必须对应 []string。
- 嵌套结构?用嵌套 struct:若 JSON 含嵌套对象(如 "meta": {"version": "1.0"}),定义对应子结构体并嵌入。
- 调试技巧:先用 json.RawMessage 解析为原始字节,再打印确认格式;或用在线工具(如 jsonlint.com)验证 JSON 合法性。
- 性能提示:对大量数据,考虑使用 json.Decoder 流式解析(decoder.Decode(&v)),避免一次性加载全部内存。
掌握导出规则与数据结构映射,是 Go JSON 处理的核心基础。只要确保字段可导出、标签准确、容器类型([]T vs T)匹配,encoding/json 就能稳定可靠地完成解析任务。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











