Golang处理稍复杂JSON数据的实用技巧
Golang处理稍复杂JSON数据的实用技巧
在处理复杂的JSON结构时,我似乎无法从json.Unmarshal得到任何返回结果。
以下是来自Shopify API的响应示例:
{“products”:[{“id”:2570195271760,“title”:“Sample Product”,“body_html”:“Example of an html body”}]}
我尝试了以下方法:
Resio, _ := ioutil.ReadAll(res.Body)
JSONProducts := string(Resio)
type Product struct {
Id string `json:"id"`
}
type Response struct {
Products []Product `json:"products"`
}
ProductsList := Response{}
json.Unmarshal([]byte(JSONProducts), &ProductsList)
fmt.Println(ProductsList.Products)
fmt.Println(ProductsList)
但我的响应看起来像这样:
[{}] {[{}]}
我哪里做错了?
更多关于Golang处理稍复杂JSON数据的实用技巧的实战教程也可以访问 https://www.itying.com/category-94-b0.html
这段代码看起来与我用来解析一个相当复杂JSON文件的代码几乎完全相同,但我会尝试将 title 和 body_html 元素添加到 Product 结构体中,看看是否有所不同(不过按理说不应该,因为我的代码也没有使用所有元素)。同时,打印 JSONProducts 字符串以确保该字符串包含你期望的内容。
type Product struct {
Id string `json:"id"`
Title `json:"title"`
BodyHtml `json:"body_html"
}
由于JSON输入中的id属性是JSON数字类型,因此无法将其反序列化为Go的string类型。请将Id的类型更改为int64,并添加另外两个属性:
type Product struct {
Id int64 `json:"id"`
Title string `json:"title"`
Body string `json:"body_html"`
}
查看此链接获取可运行的示例。
该代码的输出为:
[{2570195271760 Sample Product Example of an html body}]
{[{2570195271760 Sample Product Example of an html body}]}
你的问题在于JSON中的id字段是数值类型(2570195271760),而你在Go结构体中将其定义为string类型。json.Unmarshal在类型不匹配时不会报错,而是会保留字段的零值(对于字符串就是空字符串)。
以下是修正后的代码:
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
)
func main() {
// 模拟API响应数据
jsonData := `{"products":[{"id":2570195271760,"title":"Sample Product","body_html":"Example of an html body"}]}`
type Product struct {
ID int64 `json:"id"` // 改为int64类型
Title string `json:"title,omitempty"`
BodyHTML string `json:"body_html,omitempty"`
}
type Response struct {
Products []Product `json:"products"`
}
var response Response
err := json.Unmarshal([]byte(jsonData), &response)
if err != nil {
fmt.Println("解析错误:", err)
return
}
fmt.Printf("完整响应: %+v\n", response)
fmt.Printf("产品列表: %+v\n", response.Products)
// 访问第一个产品
if len(response.Products) > 0 {
fmt.Printf("产品ID: %d\n", response.Products[0].ID)
fmt.Printf("产品标题: %s\n", response.Products[0].Title)
}
}
如果你确实需要将ID保持为字符串类型,可以在结构体中使用json.Number类型:
type Product struct {
ID json.Number `json:"id"` // 使用json.Number
Title string `json:"title,omitempty"`
BodyHTML string `json:"body_html,omitempty"`
}
// 使用时可以转换为字符串或数值
idStr := product.ID.String()
idInt, _ := product.ID.Int64()
或者使用interface{}类型配合类型断言:
type Product struct {
ID interface{} `json:"id"`
Title string `json:"title,omitempty"`
BodyHTML string `json:"body_html,omitempty"`
}
// 使用时进行类型判断
switch v := product.ID.(type) {
case float64:
fmt.Printf("数值ID: %.0f\n", v)
case string:
fmt.Printf("字符串ID: %s\n", v)
}
对于更复杂的JSON处理,可以考虑以下技巧:
- 使用
json.RawMessage延迟解析:
type Response struct {
Products json.RawMessage `json:"products"`
}
var response Response
json.Unmarshal(data, &response)
// 稍后根据需要解析products
var products []Product
json.Unmarshal(response.Products, &products)
- 处理动态字段:
type Product struct {
ID int64 `json:"id"`
Extra map[string]interface{} `json:"-"` // 忽略已知字段外的其他字段
}
func (p *Product) UnmarshalJSON(data []byte) error {
type Alias Product
aux := &struct {
*Alias
}{
Alias: (*Alias)(p),
}
if err := json.Unmarshal(data, &aux); err != nil {
return err
}
// 提取额外字段
var m map[string]interface{}
json.Unmarshal(data, &m)
delete(m, "id")
p.Extra = m
return nil
}
- 使用指针字段处理可选字段:
type Product struct {
ID *int64 `json:"id,omitempty"` // 使用指针,nil表示字段不存在
Title *string `json:"title,omitempty"`
}
// 检查字段是否存在
if product.ID != nil {
fmt.Printf("ID存在: %d\n", *product.ID)
}
确保始终检查json.Unmarshal返回的错误,这能帮助你快速定位解析问题。

