为了账号安全,请及时绑定邮箱和手机立即绑定

JSON Unmarshal 不适用于 relect 创建的动态结构

JSON Unmarshal 不适用于 relect 创建的动态结构

Go
慕雪6442864 2022-06-01 16:48:04
我试图通过使用动态创建的结构来解析 JSON 文件,但显然我做错了什么。有人可以告诉我们我在这里做错了什么:structured := make(map[string][]reflect.StructField)structured["Amqp1"] = []reflect.StructField{    reflect.StructField{        Name: "Test",        Type: reflect.TypeOf(""),        Tag:  reflect.StructTag(`json:"test"`),    },    reflect.StructField{        Name: "Float",        Type: reflect.TypeOf(5.5),        Tag:  reflect.StructTag(`json:"float"`),    },    reflect.StructField{        Name: "Connections",        Type: reflect.TypeOf([]Connection{}),        Tag:  reflect.StructTag(`json:"connections"`),    },}sections := []reflect.StructField{}for sect, params := range structured {    sections = append(sections,        reflect.StructField{            Name: sect,            Type: reflect.StructOf(params),        },    )}parsed := reflect.New(reflect.StructOf(sections)).Elem()if err := json.Unmarshal([]byte(JSONConfigContent), &parsed); err != nil {    fmt.Printf("unable to parse data from provided configuration file: %s\n", err)    os.Exit(1)}https://play.golang.org/p/C2I4Pduduyg提前致谢。
查看完整描述

3 回答

?
慕慕森

TA贡献1856条经验 获得超17个赞

reflect.New 返回一个表示指针的值。更改第 69 行:

fmt.Printf(">>> %v", &parsed)

结果:

>>> <struct { Amqp1 struct { Test string "json:\"test\""; Float float64 "json:\"float\""; Connections []main.Connection "json:\"connections\"" } } Value>



查看完整回答
反对 回复 2022-06-01
?
慕娘9325324

TA贡献1783条经验 获得超4个赞

我会推荐一些非常不同的东西。我通常会尽可能避免反思。您可以通过简单地为您期望的每种配置类型提供结构来完成您想要做的事情,然后进行初始“预解组”以确定您应该按名称实际使用的配置类型(在这种情况下是JSON 对象的键):


package main


import (

    "encoding/json"

    "fmt"

    "os"

)


//Amqp1 config struct

type Amqp1 struct {

    Config struct {

        Test        string       `json:"test"`

        Float       float64      `json:"float"`

        Connections []Connection `json:"connections"`

    } `json:"Amqp1"`

}


//Connection struct

type Connection struct {

    Type string `json:"type"`

    URL  string `json:"url"`

}


//JSONConfigContent json

const JSONConfigContent = `{

    "Amqp1": {

        "test": "woobalooba",

        "float": 5.5,

        "connections": [

            {"type": "test1", "url": "booyaka"},

            {"type": "test2", "url": "foobar"}

        ]

    }

}`


func main() {

    configMap := make(map[string]interface{})

    if err := json.Unmarshal([]byte(JSONConfigContent), &configMap); err != nil {

        fmt.Printf("unable to parse data from provided configuration file: %s\n", err)

        os.Exit(1)

    }


    //get config name

    var configName string

    for cfg := range configMap {

        configName = cfg

        break

    }


    //unmarshal appropriately

    switch configName {

    case "Amqp1":

        var amqp1 Amqp1

        if err := json.Unmarshal([]byte(JSONConfigContent), &amqp1); err != nil {

            fmt.Printf("unable to parse data from provided configuration file: %s\n", err)

            os.Exit(1)

        }

        fmt.Printf("%s >>\n", configName)

        fmt.Printf("Test: %s\n", amqp1.Config.Test)

        fmt.Printf("Float: %v\n", amqp1.Config.Float)

        fmt.Printf("Connections: %#v\n", amqp1.Config.Connections)


    default:

        fmt.Printf("unknown config encountered: %s\n", configName)

        os.Exit(1)

    }

}

最初的“预解组”发生在 main() 的第二行,到一个普通的映射,其中键是字符串,值是 interface{},因为你不在乎。您这样做只是为了获取实际的配置类型,这是第一个嵌套对象的键。


查看完整回答
反对 回复 2022-06-01
?
慕丝7291255

TA贡献1859条经验 获得超6个赞

你想用来.Interface()返回实际的底层值,它应该是一个指向具体匿名结构的指针。


请注意,该reflect.New函数返回一个reflect.Value 表示指向指定类型的新零值的指针。Interface在这种情况下,该方法返回该指针,interface{}这就是您所需要的json.Unmarshal。


如果在解组之后,您需要结构的非指针,您可以再次反射并使用它reflect.ValueOf(parsed).Elem().Interface()来有效地取消引用指针。


parsed := reflect.New(reflect.StructOf(sections)).Interface()

if err := json.Unmarshal([]byte(JSONConfigContent), parsed); err != nil {

    fmt.Printf("unable to parse data from provided configuration file: %s\n", err)

    os.Exit(1)

}

https://play.golang.org/p/Bzu1hUyKjvM


查看完整回答
反对 回复 2022-06-01
  • 3 回答
  • 0 关注
  • 88 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信