Golang中解析含顶层匿名数组的JSON并优雅提取tokens的方法咨询
Golang中解析含顶层匿名数组的JSON并优雅提取tokens的方法咨询
嗨,我完全懂你现在的困扰——用any反复做类型断言确实又繁琐又不够安全,看起来也不优雅。其实你完全可以用结构体来解析这个JSON,之前没成功大概率是没处理好顶层的匿名数组结构,我来给你一步步梳理怎么优化:
首先,我们根据你的JSON结构定义对应的Go结构体,把JSON里的层级对应起来:
// 单个token的结构体,对应JSON里的tokens数组元素 type Token struct { Name string `json:"name"` Type string `json:"type"` IsList bool `json:"isList"` Default string `json:"default"` Description *string `json:"description"` // 用指针处理null值,区分空字符串和null } // 顶层数组的元素结构体,包含tokens字段 type QueryResult struct { QueryId string `json:"queryId"` QueryType string `json:"queryType"` Description *string `json:"description"` Tokens []Token `json:"tokens"` }
这里Description用指针类型是因为JSON里它可能是null,指针可以明确区分“null”和空字符串的差异;如果不需要这种区分,换成普通字符串也可以,Unmarshal时会把null转成空字符串。
接下来修改你的getRequest函数,用这些结构体来解析,代码会清爽很多:
func getRequest(authToken string) error { reqUrl := fmt.Sprintf("https://host.com?params") req, err := http.NewRequest(http.MethodGet, reqUrl, nil) if err != nil { return err } req.Header.Set("Authorization", "Bearer "+authToken) resp, err := http.DefaultClient.Do(req) if err != nil { return err } defer resp.Body.Close() // 把defer放在resp成功获取后,避免空指针问题 body, err := io.ReadAll(resp.Body) if err != nil { return err } // 关键:JSON顶层是数组,所以要Unmarshal到[]QueryResult切片类型 var results []QueryResult if err := json.Unmarshal(body, &results); err != nil { return err } // 优雅遍历提取tokens for _, result := range results { for _, token := range result.Tokens { fmt.Printf(" - Name: %s\n", token.Name) fmt.Printf(" - Type: %s\n", token.Type) fmt.Printf(" - IsList: %t\n", token.IsList) fmt.Printf(" - Default: %s\n", token.Default) // 处理可能为null的描述字段 if token.Description != nil { fmt.Printf(" - Description: %s\n\n", *token.Description) } else { fmt.Println(" - Description: null\n") } } } return nil }
这样做的好处很明显:
- 类型安全:编译阶段就能检查字段类型,避免运行时类型断言出错
- 代码简洁:不用反复写繁琐的类型断言,直接通过结构体字段访问
- 可读性强:结构体定义清晰展示了JSON的层级结构,后续维护或扩展其他字段也很方便
如果你真的只关心tokens,甚至可以简化结构体(比如只保留外层的Tokens字段),但上面的方式是最规范、扩展性最好的方案。
内容来源于stack exchange
相关产品推荐
相关产品推荐

