我有一个以某种方式关注的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
的解决方案。但是,不要将其标记为答案,因为需要知道在没有其他选择的所有情况下,如何轻松地做到这一点。
答案 0 :(得分:4)
问题是您的类型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]
答案 1 :(得分:0)
范围子句提供了一种遍历数组,切片,字符串,映射或通道的方法。因此,在将struct转换为上述类型之一之前,您不能在struct上扩展。
要遍历struct字段,可以通过为struct创建一个反射值切片来进行反射。
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
返回struct v中的字段数。 v的种类不是结构。
func (v Value) NumField() int
Field
返回结构的第i个字段 v。如果v的Kind不是Struct或i超出范围,它会感到恐慌。
func (v Value) Field(i int) Value
接口返回v的当前值作为接口{}。
func (v Value) Interface() (i interface{})