You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Go中用interface{}将JSON转为泛型结构体而非map[string]interface{}?

Go中将JSON解析为含多类型字段的结构体方案

问题描述

需要将JSON转换为支持多类型字段的结构体,使用interface{}兼容不同数据类型,但当前用json.Unmarshal解析后得到的是map[string]interface{},期望直接得到结构体对象。

示例JSON:

{
  "animal": "Elephant",
  "age": 15,
  "location": {
    "country": "Kenya",
    "continent": "Africa"
  },
  "diet": ["grass", "fruit", "vegetables"]
}

当前使用的代码:

package main

import (
    "encoding/json"
    "fmt"
)

func main() {
    jsonData := `{
        "animal": "Elephant",
        "age": 15,
        "location": {
            "country": "Kenya",
            "continent": "Africa"
        },
        "diet": ["grass", "fruit", "vegetables"]
    }`
    
    var result interface{}
    
    err := json.Unmarshal([]byte(jsonData), &result)
    if err != nil {
        fmt.Println("Error:", err)
    }
    
    fmt.Printf("Result: %+v\n", result)
}

当前输出:

map[age:15 animal:Elephant diet:[grass fruit vegetables] location:map[continent:Africa country:Kenya]]

期望输出:

{Animal:Elephant Age:15 Location:{Country:Kenya Continent:Africa} Diet:[grass fruit vegetables]}

尝试过mapstructure.Decode但未成功,需解决该问题。

解决方案

方案一:提前定义对应结构体(推荐)

Go是静态类型语言,必须提前定义结构体类型才能解析为结构体对象。即使字段需要兼容多类型,也可以将字段类型设为interface{},同时通过JSON标签映射字段:

package main

import (
    "encoding/json"
    "fmt"
)

// 若明确location的结构,可定义子结构体
type Location struct {
    Country  string `json:"country"`
    Continent string `json:"continent"`
}

type Animal struct {
    Animal   interface{} `json:"animal"`
    Age      interface{} `json:"age"`
    // 若location结构不确定,可改为interface{},解析后会是map[string]interface{}
    Location Location    `json:"location"`
    Diet     interface{} `json:"diet"`
}

func main() {
    jsonData := `{
        "animal": "Elephant",
        "age": 15,
        "location": {
            "country": "Kenya",
            "continent": "Africa"
        },
        "diet": ["grass", "fruit", "vegetables"]
    }`
    
    var result Animal
    err := json.Unmarshal([]byte(jsonData), &result)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    
    fmt.Printf("Result: %+v\n", result)
}

执行后输出符合预期:

Result: {Animal:Elephant Age:15 Location:{Country:Kenya Continent:Africa} Diet:[grass fruit vegetables]}

方案二:用mapstructure从map转结构体(适用于结构不确定场景)

如果无法提前明确JSON结构,可先将JSON解析为map[string]interface{},再通过mapstructure转换为结构体。注意需先安装依赖:go get github.com/mitchellh/mapstructure

package main

import (
    "encoding/json"
    "fmt"
    "github.com/mitchellh/mapstructure"
)

type Animal struct {
    Animal   interface{}
    Age      interface{}
    Location interface{}
    Diet     interface{}
}

func main() {
    jsonData := `{
        "animal": "Elephant",
        "age": 15,
        "location": {
            "country": "Kenya",
            "continent": "Africa"
        },
        "diet": ["grass", "fruit", "vegetables"]
    }`
    
    // 先解析为map
    var rawMap map[string]interface{}
    err := json.Unmarshal([]byte(jsonData), &rawMap)
    if err != nil {
        fmt.Println("Unmarshal error:", err)
        return
    }
    
    // 再将map转换为结构体
    var result Animal
    err = mapstructure.Decode(rawMap, &result)
    if err != nil {
        fmt.Println("Decode error:", err)
        return
    }
    
    fmt.Printf("Result: %+v\n", result)
}

之前使用mapstructure失败的原因是直接传入了JSON字节,而mapstructure.Decode接收的是map[string]interface{}类型数据,而非原始JSON字节。

关键说明

Go是静态类型语言,无法动态生成结构体类型,必须提前定义结构体的字段结构。如果JSON结构完全不确定,map[string]interface{}是更灵活的选择,但如果需要结构体形式,必须显式定义结构体类型。

内容的提问来源于stack exchange,提问作者Charles Braga

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 02:15:09