Golang如何将动态JSON转换为结构体
Golang如何将动态JSON转换为结构体 我在将API返回的JSON转换为静态结构体时遇到了一些问题,以下是我的JSON示例:
{
"layoutID": 1,
"data": [
{
"widgetID": 1,
"name": "widget 1",
"type": "product",
"data": [
{
"productID": 1,
"name": "product 1"
}
]
},
{
"widgetID": 1,
"name": "widget 2",
"type": "voucher",
"data": [
{
"voucherID": 1,
"name": "voucher 1"
}
]
}
]
}
我想为这个JSON创建一个结构体,但不知道如何转换。我尝试使用接口进行转换和类型断言,但没有成功。
你能帮帮我吗?谢谢
更多关于Golang如何将动态JSON转换为结构体的实战教程也可以访问 https://www.itying.com/category-94-b0.html
我认为你可以在这里找到答案:http://mattyjwilliams.blogspot.com/2013/01/using-go-to-unmarshal-json-lists-with.html 如果你还有更多问题,请告诉我们。
在你编写的循环中,Data 的类型是 widget。你不需要进行类型转换。你需要做的是遍历其中的 Data https://play.golang.org/p/QoLQxyv1zKr
https://mholt.github.io/json-to-go/ https://blog.golang.org/json
你也可以将接收对象定义为 map[string]interface{},JSON 反序列化会递归地填充所有细节。
func main() {
fmt.Println("hello world")
}
为什么不直接反序列化到你创建的结构体中呢?
var l Layout
if err := json.Unmarshal(byt, &l); err != nil {
panic(err)
}
fmt.Printf("layout: %+v",l)
谢谢 @eudore。
我已经尝试过这个方法,但问题仍未解决,以下是结果:
type AutoGenerated struct {
LayoutID int `json:"layoutID"`
Data []struct {
WidgetID int `json:"widgetID"`
Name string `json:"name"`
Type string `json:"type"`
Data []struct {
ProductID int `json:"productID"`
Name string `json:"name"`
} `json:"data"`
} `json:"data"`
}
继续讨论 尝试将动态 JSON 转换为结构体:
非常感谢你的帮助,这确实帮了我大忙。但是,在反序列化之后我又遇到了另一个问题,我发现 Widget 结构体中的 data 是 []interface{} 类型。
我尝试转换这些代码,但结果是错误 invalid type assertion。我该怎么做,或者有其他方法可以将其转换为 Product 和 Voucher 结构体吗?
以下是我检查后的改进代码。 https://play.golang.org/p/2zmGTlbC9pB
非常感谢! 👍
对于动态JSON结构,可以使用json.RawMessage配合自定义的UnmarshalJSON方法。以下是解决方案:
package main
import (
"encoding/json"
"fmt"
)
type Layout struct {
LayoutID int `json:"layoutID"`
Data []WidgetWrapper `json:"data"`
}
type WidgetWrapper struct {
WidgetID int `json:"widgetID"`
Name string `json:"name"`
Type string `json:"type"`
Data json.RawMessage `json:"data"`
}
func (w *WidgetWrapper) UnmarshalJSON(data []byte) error {
type Alias WidgetWrapper
aux := &struct {
*Alias
}{
Alias: (*Alias)(w),
}
if err := json.Unmarshal(data, aux); err != nil {
return err
}
switch w.Type {
case "product":
var products []Product
if err := json.Unmarshal(w.Data, &products); err != nil {
return err
}
w.Data = json.RawMessage(products)
case "voucher":
var vouchers []Voucher
if err := json.Unmarshal(w.Data, &vouchers); err != nil {
return err
}
w.Data = json.RawMessage(vouchers)
}
return nil
}
type Product struct {
ProductID int `json:"productID"`
Name string `json:"name"`
}
type Voucher struct {
VoucherID int `json:"voucherID"`
Name string `json:"name"`
}
func main() {
jsonStr := `{
"layoutID": 1,
"data": [
{
"widgetID": 1,
"name": "widget 1",
"type": "product",
"data": [
{
"productID": 1,
"name": "product 1"
}
]
},
{
"widgetID": 1,
"name": "widget 2",
"type": "voucher",
"data": [
{
"voucherID": 1,
"name": "voucher 1"
}
]
}
]
}`
var layout Layout
if err := json.Unmarshal([]byte(jsonStr), &layout); err != nil {
panic(err)
}
fmt.Printf("Layout ID: %d\n", layout.LayoutID)
for _, widget := range layout.Data {
fmt.Printf("Widget: %s (Type: %s)\n", widget.Name, widget.Type)
}
}
如果需要访问具体类型的数据,可以添加一个方法:
func (w *WidgetWrapper) GetData() interface{} {
switch w.Type {
case "product":
var products []Product
json.Unmarshal(w.Data, &products)
return products
case "voucher":
var vouchers []Voucher
json.Unmarshal(w.Data, &vouchers)
return vouchers
}
return nil
}
这样可以在解析时根据type字段动态处理不同的数据结构。


