Go语言中如何处理嵌套非结构化JSON并提取指定数据
Go语言从非结构化JSON中提取特定数据
需求说明
给定一段非结构化JSON数据,要求当Material字段下的Foo1为非空数组时,提取Material->Foo1中的method值,同时获取classifications->Foo1中的desc值。
原代码问题
你提供的示例代码中,结构体New仅定义了Desc字段,无法适配Material下的数组结构;且用map[string]map[string]New接收整个JSON也不合适,因为Material的字段值是数组而非New类型结构体。
解决方案
由于JSON结构非结构化,字段值类型不统一(对象、数组并存),使用map[string]interface{}解析更灵活,通过类型断言逐层提取目标数据,同时加入格式校验保证代码健壮性。
完整实现代码
package main import ( "encoding/json" "fmt" ) func main() { bJson := `{ "classifications": { "Foo1": { "desc": "It may be possible.", "sol": "The backups.", "ref": { "Sensitive Information": "https://www.sensitive_Information.html", "Control Sphere": "https://ww.example.org/data.html" } }, "Bar1": { "desc": "The target", "sol": "should be used.", "ref": { "ABC: Srgery": "https://www.orp.org/" } } }, "Material": { "Backup file": [], "Foo1": [ { "method": "GET", "info": "It is not set", "level": 1, "parameter": "", "referer": "", "module": "diq", "curl_command": "curl \"https://example.com/\"", "wsg": [ "CONF-12", "O-Policy" ] }], "foo2": [], "Bar1": [] }, "anomalies": { "Server Error": [], "Resource consumption": [] }, "additionals": { "web technology": [], "Methods": [] }, "infos": { "url": "https://example.com/", "date": "Thu, 08 Dec 2022 06:52:04 +0000"} }` var data map[string]interface{} if err := json.Unmarshal([]byte(bJson), &data); err != nil { fmt.Println("JSON解析失败:", err) return } // 提取Material下的Foo1并检查是否非空 material, ok := data["Material"].(map[string]interface{}) if !ok { fmt.Println("Material字段格式不符合预期") return } foo1Material, ok := material["Foo1"].([]interface{}) if !ok || len(foo1Material) == 0 { fmt.Println("Material->Foo1为空或格式错误") return } // 提取method值 foo1Item, ok := foo1Material[0].(map[string]interface{}) if !ok { fmt.Println("Material->Foo1元素格式错误") return } method, ok := foo1Item["method"].(string) if !ok { fmt.Println("method字段不存在或类型错误") return } // 提取classifications下Foo1的desc值 classifications, ok := data["classifications"].(map[string]interface{}) if !ok { fmt.Println("classifications字段格式不符合预期") return } foo1Class, ok := classifications["Foo1"].(map[string]interface{}) if !ok { fmt.Println("classifications->Foo1格式错误") return } desc, ok := foo1Class["desc"].(string) if !ok { fmt.Println("desc字段不存在或类型错误") return } // 输出结果 fmt.Printf("Method is %s\n", method) fmt.Printf("desc is %s\n", desc) }
代码说明
- 用
map[string]interface{}接收整个JSON,适配非结构化的多变结构 - 逐层进行类型断言,每一步都做格式校验,避免程序panic
- 先校验
Material->Foo1是否为非空数组,再提取第一个元素的method - 再提取
classifications->Foo1中的desc值 - 加入错误处理,提升代码健壮性
预期输出
Method is GET desc is It may be possible.
扩展说明
如果需要批量处理Material下所有非空的键(比如Bar1),可以遍历Material的键值对,逐个检查数组是否非空,再对应提取classifications中同名键的desc值。
内容的提问来源于stack exchange,提问作者Soulja
相关产品推荐
相关产品推荐

