Golang中如何将Interface{}转换为Struct
Golang中如何将Interface{}转换为Struct 你好,
我将一个 JSON 文件(见下方示例)加载到一个通用的 interface{} 对象中,并希望将其转换为一个正式的结构体。我的问题是,'properties' → 'help' → 'properties' 数组会不断重复,直到子 'help' 数组为 NULL,而我们事先并不知道这一点。
{
"list": {
"lstexampleA": [
{ "properties": [
{
"with": "OPTION1",
"help": [
{
"properties": [
{
"with": null,
"help": null,
"element": "MP0001"
}
]
},
{
"properties": [
{
"with": null,
"help": null,
"element": "MP0002"
}
]
}
]
},
{
"with": "OPTION6",
"help": null,
"element": 10
}
],
"element": 100
}
],
"lstexampleB": [ .....
]
}
}
所以,也许需要类似这样的结构…
var olists []oList
type oList struct {
OWith string
OHelp []oList
OElement interface{}
}
是否有标准的方法来遍历 interface{} 对象,并在遍历过程中构建结构体…
谢谢
更多关于Golang中如何将Interface{}转换为Struct的实战教程也可以访问 https://www.itying.com/category-94-b0.html
@christophberger。非常感谢。对我来说效果非常好。
更多关于Golang中如何将Interface{}转换为Struct的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
完美!很高兴听到它在你的场景中运行良好。
你好 @Steff,欢迎来到论坛。
json.Unmarshall 可以处理相同类型的嵌套数据。
要让 Unmarshal() 在 Go 中构建嵌套结构体,请使用指针来描述子结构体:
var lists []List
type List struct {
With string
Help []oList
Element *List
}
我修改了 Unmarshal 文档中的示例 来解析嵌套的 Animal 数据作为概念验证:
var jsonBlob = []byte(`[
{"Name": "Platypus", "Order": "Monotremata", "Animal":
{"Name": "Plotypas", "Order": "Manatremoto", "Animal":
{"Name": "Plytapos", "Order": "Menetromata" }
}
},
{"Name": "Quoll", "Order": "Dasyuromorphia"}
]`)
type Animal struct {
Name string
Order string
Animal *Animal
}
var animals []Animal
err := json.Unmarshal(jsonBlob, &animals)
if err != nil {
fmt.Println("error:", err)
}
spew.Dump(animals)
完整、可运行的代码可在 Playground 中找到。
输出(确实,spew.Dump() 在这里可能有点过于冗长,只需看整体结构而不是细节):
([]main.Animal) (len=2 cap=4) {
(main.Animal) {
Name: (string) (len=8) "Platypus",
Order: (string) (len=11) "Monotremata",
Animal: (*main.Animal)(0xc0000a05a0)({
Name: (string) (len=8) "Plotypas",
Order: (string) (len=11) "Manatremoto",
Animal: (*main.Animal)(0xc0000a05d0)({
Name: (string) (len=8) "Plytapos",
Order: (string) (len=11) "Menetromata",
Animal: (*main.Animal)(<nil>)
})
})
},
(main.Animal) {
Name: (string) (len=5) "Quoll",
Order: (string) (len=14) "Dasyuromorphia",
Animal: (*main.Animal)(<nil>)
}
}
在Go语言中,处理这种嵌套不确定深度的JSON数据,可以使用递归和类型断言。以下是完整的解决方案:
package main
import (
"encoding/json"
"fmt"
)
// 定义结构体
type OList struct {
OWith string `json:"with"`
OHelp []OList `json:"help"`
OElement any `json:"element"`
}
// 递归解析函数
func parseProperties(data any) []OList {
var result []OList
// 类型断言检查是否为slice
if slice, ok := data.([]any); ok {
for _, item := range slice {
if itemMap, ok := item.(map[string]any); ok {
olist := OList{}
// 解析with字段
if withVal, ok := itemMap["with"].(string); ok {
olist.OWith = withVal
} else if withVal, ok := itemMap["with"]; ok && withVal == nil {
olist.OWith = ""
}
// 解析element字段
olist.OElement = itemMap["element"]
// 递归解析help字段
if helpVal, ok := itemMap["help"]; ok && helpVal != nil {
if helpSlice, ok := helpVal.([]any); ok && len(helpSlice) > 0 {
for _, helpItem := range helpSlice {
if helpMap, ok := helpItem.(map[string]any); ok {
if props, ok := helpMap["properties"]; ok {
olist.OHelp = append(olist.OHelp, parseProperties(props)...)
}
}
}
}
}
result = append(result, olist)
}
}
}
return result
}
func main() {
// 示例JSON数据
jsonData := `{
"list": {
"lstexampleA": [
{
"properties": [
{
"with": "OPTION1",
"help": [
{
"properties": [
{
"with": null,
"help": null,
"element": "MP0001"
}
]
},
{
"properties": [
{
"with": null,
"help": null,
"element": "MP0002"
}
]
}
]
},
{
"with": "OPTION6",
"help": null,
"element": 10
}
],
"element": 100
}
]
}
}`
// 解析JSON到interface{}
var data map[string]any
if err := json.Unmarshal([]byte(jsonData), &data); err != nil {
panic(err)
}
// 获取list.lstexampleA[0].properties
listData, _ := data["list"].(map[string]any)
lstexampleA, _ := listData["lstexampleA"].([]any)
firstItem, _ := lstexampleA[0].(map[string]any)
properties, _ := firstItem["properties"].([]any)
// 递归解析
olists := parseProperties(properties)
// 打印结果
fmt.Printf("解析出 %d 个OList:\n", len(olists))
for i, item := range olists {
fmt.Printf("\n[%d] With: %s, Element: %v\n", i, item.OWith, item.OElement)
if len(item.OHelp) > 0 {
fmt.Printf(" 包含 %d 个子项:\n", len(item.OHelp))
for j, child := range item.OHelp {
fmt.Printf(" [%d] With: %s, Element: %v\n", j, child.OWith, child.OElement)
}
}
}
}
输出结果:
解析出 2 个OList:
[0] With: OPTION1, Element: <nil>
包含 2 个子项:
[0] With: , Element: MP0001
[1] With: , Element: MP0002
[1] With: OPTION6, Element: 10
这个解决方案的关键点:
- 递归函数:
parseProperties函数会递归调用自身来处理嵌套的help→properties结构 - 类型断言:使用
.(type)语法来检查interface{}的实际类型 - 空值处理:正确处理JSON中的
null值 - 灵活的类型:
OElement使用any(Go 1.18+)或interface{}来容纳不同类型的值
如果需要处理整个JSON结构(包括外层的list和lstexampleA等),可以扩展这个递归函数来遍历整个数据结构。

