代码之家  ›  专栏  ›  技术社区  ›  Mayukh Sarkar

如何从字符串表示形式中获取嵌套结构from变量?

  •  0
  • Mayukh Sarkar  · 技术社区  · 7 年前

    我有一个JSON文件看起来像

    {
        "type": "Weekly",
        "clients": [
            "gozo",
            "dva"
        ],
        "sender": "no-reply@flowace.in",
        "recipients": {
            "gozo": [
                "a@gmail.com",
                "b@hotmail.com"
            ],
            "dva": [
                "c@gmail.com",
                "d@hotmail.com"
            ]
        },
        "features": [
            "Top5UsedApps",
            "TimeSpentOnEachL3",
            "NewlyAssignedL3",
            "HoursLogged"
        ],
        "dbCloning": [
            "dva"
        ] 
    }
    

    我已经映射了如下结构。

    type receivers struct {
        Gozo []string `json:"gozo"`
        Dva  []string `json:"dva"`
        // Add more recievers
    }
    
    // Config -- The config object parsed from the JSON file
    type Config struct {
        ReportType string    `json:"type"`
        Clients    []string  `json:"clients"`
        Sender     string    `json:"sender"`
        Recipients receivers `json:"recipients"`
        Cloning    []string  `json:"dbCloning"`
    }
    

    然后在另一个源文件的某个地方,我做了如下操作,

    func main() {
        conf := LoadConfig(os.Args[1])
        for _, client := range conf.Clients {
    
            // Use the client variable of some other function calls
    
            fmt.Println(conf.Recipients[client]) // This will not work
    }
    

    conf.Recipients 直接。

    PS:考虑一下 LoadConfig 函数将JSON解组并返回 conf

    编辑1: 看起来是设计决策失误。现在来解决 map[string][]string

    2 回复  |  直到 7 年前
        1
  •  4
  •   Ullaakut    7 年前

    问题是你的类型 receivers 不应该给字段命名。它应该是一个 map[string][]string

    下面是一个工作示例:

    package main
    
    import (
        "encoding/json"
        "fmt"
    )
    
    type Config struct {
        ReportType string              `json:"type"`
        Clients    []string            `json:"clients"`
        Sender     string              `json:"sender"`
        Recipients map[string][]string `json:"recipients"`
        Cloning    []string            `json:"dbCloning"`
    }
    
    var data = []byte(`{
        "type": "Weekly",
        "clients": [
            "gozo",
            "dva"
        ],
        "sender": "no-reply@flowace.in",
        "recipients": {
            "gozo": [
                "a@gmail.com",
                "b@hotmail.com"
            ],
            "dva": [
                "c@gmail.com",
                "d@hotmail.com"
            ]
        },
        "features": [
            "Top5UsedApps",
            "TimeSpentOnEachL3",
            "NewlyAssignedL3",
            "HoursLogged"
        ],
        "dbCloning": [
            "dva"
        ] 
    }`)
    
    func main() {
        var conf Config
        json.Unmarshal(data, &conf)
    
        for _, client := range conf.Clients {
            fmt.Println(conf.Recipients[client])
        }
    }
    

    给出输出

    [a@gmail.com b@hotmail.com]
    [c@gmail.com d@hotmail.com]
    
        2
  •  0
  •   Himanshu    7 年前

    range子句提供了一种迭代数组、切片、字符串、映射或通道的方法。因此,在将struct转换为上述类型之一之前,不能在struct上设置范围。

    要在结构字段上循环,可以通过为结构创建一个reflect值片段来进行反射。

    package main
    
    import (
        "encoding/json"
        "fmt"
        "reflect"
    )
    
    type receivers struct {
        Gozo []string `json:"gozo"`
        Dva  []string `json:"dva"`
        // Add more recievers
    }
    
    // Config -- The config object parsed from the JSON file
    type Config struct {
        ReportType string    `json:"type"`
        Clients    []string  `json:"clients"`
        Sender     string    `json:"sender"`
        Recipients receivers `json:"recipients"`
        Cloning    []string  `json:"dbCloning"`
    }
    
    var data = []byte(`{
        "type": "Weekly",
        "clients": [
            "gozo",
            "dva"
        ],
        "sender": "no-reply@flowace.in",
        "recipients": {
            "gozo": [
                "a@gmail.com",
                "b@hotmail.com"
            ],
            "dva": [
                "c@gmail.com",
                "d@hotmail.com"
            ]
        },
        "features": [
            "Top5UsedApps",
            "TimeSpentOnEachL3",
            "NewlyAssignedL3",
            "HoursLogged"
        ],
        "dbCloning": [
            "dva"
        ] 
    }`)
    
    func main() {
        var conf Config
        if err := json.Unmarshal(data, &conf); err != nil{
            fmt.Println(err)
        }
    
        v := reflect.ValueOf(conf.Recipients)
    
        values := make([]interface{}, v.NumField())
    
        for i := 0; i < v.NumField(); i++ {
            values[i] = v.Field(i).Interface()
        }
    
        fmt.Println(values)
    }
    

    工作代码 Go Playground

    NumField 返回结构v中的字段数。它会恐慌如果

    func (v Value) NumField() int
    

    Field 返回结构的第i个字段

    func (v Value) Field(i int) Value
    

    接口以接口{}的形式返回v的当前值。

    func (v Value) Interface() (i interface{})