猿问

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

我试图通过使用动态创建的结构来解析 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


提前致谢。


慕雪6442864
浏览 115回答 3
3回答

慕慕森

reflect.New 返回一个表示指针的值。更改第 69 行:fmt.Printf(">>>&nbsp;%v",&nbsp;&parsed)结果:>>>&nbsp;<struct&nbsp;{&nbsp;Amqp1&nbsp;struct&nbsp;{&nbsp;Test&nbsp;string&nbsp;"json:\"test\"";&nbsp;Float&nbsp;float64&nbsp;"json:\"float\"";&nbsp;Connections&nbsp;[]main.Connection&nbsp;"json:\"connections\""&nbsp;}&nbsp;}&nbsp;Value>

慕娘9325324

我会推荐一些非常不同的东西。我通常会尽可能避免反思。您可以通过简单地为您期望的每种配置类型提供结构来完成您想要做的事情,然后进行初始“预解组”以确定您应该按名称实际使用的配置类型(在这种情况下是JSON 对象的键):package mainimport (&nbsp; &nbsp; "encoding/json"&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "os")//Amqp1 config structtype Amqp1 struct {&nbsp; &nbsp; Config struct {&nbsp; &nbsp; &nbsp; &nbsp; Test&nbsp; &nbsp; &nbsp; &nbsp; string&nbsp; &nbsp; &nbsp; &nbsp;`json:"test"`&nbsp; &nbsp; &nbsp; &nbsp; Float&nbsp; &nbsp; &nbsp; &nbsp;float64&nbsp; &nbsp; &nbsp; `json:"float"`&nbsp; &nbsp; &nbsp; &nbsp; Connections []Connection `json:"connections"`&nbsp; &nbsp; } `json:"Amqp1"`}//Connection structtype Connection struct {&nbsp; &nbsp; Type string `json:"type"`&nbsp; &nbsp; URL&nbsp; string `json:"url"`}//JSONConfigContent jsonconst JSONConfigContent = `{&nbsp; &nbsp; "Amqp1": {&nbsp; &nbsp; &nbsp; &nbsp; "test": "woobalooba",&nbsp; &nbsp; &nbsp; &nbsp; "float": 5.5,&nbsp; &nbsp; &nbsp; &nbsp; "connections": [&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {"type": "test1", "url": "booyaka"},&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {"type": "test2", "url": "foobar"}&nbsp; &nbsp; &nbsp; &nbsp; ]&nbsp; &nbsp; }}`func main() {&nbsp; &nbsp; configMap := make(map[string]interface{})&nbsp; &nbsp; if err := json.Unmarshal([]byte(JSONConfigContent), &configMap); err != nil {&nbsp; &nbsp; &nbsp; &nbsp; fmt.Printf("unable to parse data from provided configuration file: %s\n", err)&nbsp; &nbsp; &nbsp; &nbsp; os.Exit(1)&nbsp; &nbsp; }&nbsp; &nbsp; //get config name&nbsp; &nbsp; var configName string&nbsp; &nbsp; for cfg := range configMap {&nbsp; &nbsp; &nbsp; &nbsp; configName = cfg&nbsp; &nbsp; &nbsp; &nbsp; break&nbsp; &nbsp; }&nbsp; &nbsp; //unmarshal appropriately&nbsp; &nbsp; switch configName {&nbsp; &nbsp; case "Amqp1":&nbsp; &nbsp; &nbsp; &nbsp; var amqp1 Amqp1&nbsp; &nbsp; &nbsp; &nbsp; if err := json.Unmarshal([]byte(JSONConfigContent), &amqp1); err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Printf("unable to parse data from provided configuration file: %s\n", err)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; os.Exit(1)&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; fmt.Printf("%s >>\n", configName)&nbsp; &nbsp; &nbsp; &nbsp; fmt.Printf("Test: %s\n", amqp1.Config.Test)&nbsp; &nbsp; &nbsp; &nbsp; fmt.Printf("Float: %v\n", amqp1.Config.Float)&nbsp; &nbsp; &nbsp; &nbsp; fmt.Printf("Connections: %#v\n", amqp1.Config.Connections)&nbsp; &nbsp; default:&nbsp; &nbsp; &nbsp; &nbsp; fmt.Printf("unknown config encountered: %s\n", configName)&nbsp; &nbsp; &nbsp; &nbsp; os.Exit(1)&nbsp; &nbsp; }}最初的“预解组”发生在 main() 的第二行,到一个普通的映射,其中键是字符串,值是 interface{},因为你不在乎。您这样做只是为了获取实际的配置类型,这是第一个嵌套对象的键。

慕丝7291255

你想用来.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 {&nbsp; &nbsp; fmt.Printf("unable to parse data from provided configuration file: %s\n", err)&nbsp; &nbsp; os.Exit(1)}https://play.golang.org/p/Bzu1hUyKjvM
随时随地看视频慕课网APP

相关分类

Go
我要回答