Go语言解析非结构化JSON并提取目标列表的解决方案
在Go中解析非结构化JSON并提取目标列表的方案
你的问题核心是这个JSON顶层是混合类型的数组(包含数组、字符串、null),直接json.Unmarshal到单一struct或map会失败,因为类型不匹配。可以通过以下步骤解决:
步骤1:定义目标数据的结构体
先把你要提取的列表元素对应的结构体定义好,字段名和JSON键一一对应:
type User struct { UserID string `json:"user_id"` Username string `json:"username"` } type Item struct { ID string `json:"id"` Text string `json:"text"` User User `json:"user"` CreatedAtUTC string `json:"created_at_utc"` Status string `json:"status"` }
步骤2:解析顶层混合数组,提取目标元素
先将整个响应Unmarshal到[]interface{}类型(适配顶层数组的混合元素类型),然后提取第一个元素,再将其转换为目标结构体切片:
package main import ( "encoding/json" "fmt" "io" "net/http" ) type User struct { UserID string `json:"user_id"` Username string `json:"username"` } type Item struct { ID string `json:"id"` Text string `json:"text"` User User `json:"user"` CreatedAtUTC string `json:"created_at_utc"` Status string `json:"status"` } func main() { res, err := http.Get("url_of_server") if err != nil { fmt.Printf("请求失败: %v\n", err) return } defer res.Body.Close() body, err := io.ReadAll(res.Body) if err != nil { fmt.Printf("读取响应失败: %v\n", err) return } // 先Unmarshal到混合类型数组,适配顶层的多样元素 var raw []interface{} if err := json.Unmarshal(body, &raw); err != nil { fmt.Printf("解析JSON失败: %v\n", err) return } // 提取第一个元素,断言为数组类型(即你要的目标列表) rawItems, ok := raw[0].([]interface{}) if !ok { fmt.Println("第一个元素不是数组类型") return } // 方式1:重新序列化+反序列化,简洁易维护 itemsJSON, err := json.Marshal(rawItems) if err != nil { fmt.Printf("序列化失败: %v\n", err) return } var items []Item if err := json.Unmarshal(itemsJSON, &items); err != nil { fmt.Printf("解析目标列表失败: %v\n", err) return } fmt.Printf("提取到的列表:\n%+v\n", items) // 方式2:直接遍历断言,避免二次序列化开销 var itemsDirect []Item for _, rawItem := range rawItems { itemMap, ok := rawItem.(map[string]interface{}) if !ok { continue } userMap := itemMap["user"].(map[string]interface{}) item := Item{ ID: itemMap["id"].(string), Text: itemMap["text"].(string), User: User{ UserID: userMap["user_id"].(string), Username: userMap["username"].(string), }, CreatedAtUTC: itemMap["created_at_utc"].(string), Status: itemMap["status"].(string), } itemsDirect = append(itemsDirect, item) } fmt.Printf("直接转换的列表:\n%+v\n", itemsDirect) }
关键说明
- 直接用struct/map失败的原因:顶层JSON是混合类型数组,元素分别是数组、字符串、null,无法匹配单一的struct或map类型。
- 用
[]interface{}接收整个数组后,通过类型断言提取第一个元素,再转换为目标结构体切片即可。 - 两种转换方式各有优劣:重新序列化方式代码简洁、不易出错;直接断言方式避免了二次序列化的性能开销,适合数据量较大的场景。
内容的提问来源于stack exchange,提问作者Mojtaba
相关产品推荐
相关产品推荐

