递归地展平地图golang
recursively flatten a map golang
使用下面的 json 我试图将其展平以便于访问。
有2个资源的例子在这个结构中可以有n个
"config": {
"type": "r1",
"properties": {
"p1": "10",
"p2": "10"
},
"connected": [
{
"type": "r3",
"properties": {
"p1": "10",
"p2": "10"
},
"connected": [
{}
},
],
}
自定义奉承逻辑
func keyValuePairs(m interface{}) map[string]interface{} {
kvs := make(map[string]interface{})
if reflect.ValueOf(m).Kind() == reflect.Map {
mp, ok := m.(map[string]interface{})
if ok {
var key string
var value interface{}
for k, v := range mp {
switch k {
case "type":
key = v.(string)
case "properties":
value = v
case "connected":
if collection, ok := v.([]interface{}); ok {
for _, c := range collection {
for nk, nv := range keyValuePairs(c) {
nnv, _ := nv.(map[string]interface{})
_, ok := nnv["connectedTo"]
if !ok {
nnv["connectedTo"] = key
}
kvs[nk] = nv
}
}
}
default:
for nk, nv := range keyValuePairs(v) {
kvs[nk] = nv
}
}
}
if key != "" {
kvs[key] = value
}
} else {
for k, v := range m.(map[string]interface{}) {
kvs[k] = v
}
}
}
return kvs
}
所需的输出有点波动,有些运行我得到了我需要的输出,有些执行“connectedTo”属性为空。
{
"r1": {
"p1": "10",
"p2": "10"
},
"r3" : {
"connectedTo": "r1",
"p1": "10",
"p2": "10"
},
}
我认为处决不是按顺序进行的。不对请指正
地图上的迭代顺序是随机的。详情见Why are iterations over maps random? and
现在看看你的循环:
var key string
var value interface{}
for k, v := range mp {
switch k {
case "type":
key = v.(string)
case "properties":
value = v
case "connected":
if collection, ok := v.([]interface{}); ok {
for _, c := range collection {
for nk, nv := range keyValuePairs(c) {
nnv, _ := nv.(map[string]interface{})
_, ok := nnv["connectedTo"]
if !ok {
nnv["connectedTo"] = key
}
kvs[nk] = nv
}
}
}
default:
for nk, nv := range keyValuePairs(v) {
kvs[nk] = nv
}
}
}
您在 "connected"
分支中使用了 key
变量,但是 "type"
和 "connected"
的顺序是 non-deterministic (随机)。
"type"
分支是设置 key
的分支,但如果先到达 "connected"
,则 key
将为空。
您不能依赖地图迭代顺序。
一个简单的解决方法是首先获取与"type"
关联的值并将其分配给key
(您在"connected"
分支中使用),在循环之前。
例如:
key, _ := mp["type"].(string)
value := mp["properties"]
// Now process other properties:
for k, v := range mp {
switch k {
case "type", "properties": // Already handled
case "connected":
if collection, ok := v.([]interface{}); ok {
for _, c := range collection {
for nk, nv := range keyValuePairs(c) {
nnv, _ := nv.(map[string]interface{})
_, ok := nnv["connectedTo"]
if !ok {
nnv["connectedTo"] = key
}
kvs[nk] = nv
}
}
}
default:
for nk, nv := range keyValuePairs(v) {
kvs[nk] = nv
}
}
}
使用下面的 json 我试图将其展平以便于访问。
有2个资源的例子在这个结构中可以有n个
"config": {
"type": "r1",
"properties": {
"p1": "10",
"p2": "10"
},
"connected": [
{
"type": "r3",
"properties": {
"p1": "10",
"p2": "10"
},
"connected": [
{}
},
],
}
自定义奉承逻辑
func keyValuePairs(m interface{}) map[string]interface{} {
kvs := make(map[string]interface{})
if reflect.ValueOf(m).Kind() == reflect.Map {
mp, ok := m.(map[string]interface{})
if ok {
var key string
var value interface{}
for k, v := range mp {
switch k {
case "type":
key = v.(string)
case "properties":
value = v
case "connected":
if collection, ok := v.([]interface{}); ok {
for _, c := range collection {
for nk, nv := range keyValuePairs(c) {
nnv, _ := nv.(map[string]interface{})
_, ok := nnv["connectedTo"]
if !ok {
nnv["connectedTo"] = key
}
kvs[nk] = nv
}
}
}
default:
for nk, nv := range keyValuePairs(v) {
kvs[nk] = nv
}
}
}
if key != "" {
kvs[key] = value
}
} else {
for k, v := range m.(map[string]interface{}) {
kvs[k] = v
}
}
}
return kvs
}
所需的输出有点波动,有些运行我得到了我需要的输出,有些执行“connectedTo”属性为空。
{
"r1": {
"p1": "10",
"p2": "10"
},
"r3" : {
"connectedTo": "r1",
"p1": "10",
"p2": "10"
},
}
我认为处决不是按顺序进行的。不对请指正
地图上的迭代顺序是随机的。详情见Why are iterations over maps random? and
现在看看你的循环:
var key string
var value interface{}
for k, v := range mp {
switch k {
case "type":
key = v.(string)
case "properties":
value = v
case "connected":
if collection, ok := v.([]interface{}); ok {
for _, c := range collection {
for nk, nv := range keyValuePairs(c) {
nnv, _ := nv.(map[string]interface{})
_, ok := nnv["connectedTo"]
if !ok {
nnv["connectedTo"] = key
}
kvs[nk] = nv
}
}
}
default:
for nk, nv := range keyValuePairs(v) {
kvs[nk] = nv
}
}
}
您在 "connected"
分支中使用了 key
变量,但是 "type"
和 "connected"
的顺序是 non-deterministic (随机)。
"type"
分支是设置 key
的分支,但如果先到达 "connected"
,则 key
将为空。
您不能依赖地图迭代顺序。
一个简单的解决方法是首先获取与"type"
关联的值并将其分配给key
(您在"connected"
分支中使用),在循环之前。
例如:
key, _ := mp["type"].(string)
value := mp["properties"]
// Now process other properties:
for k, v := range mp {
switch k {
case "type", "properties": // Already handled
case "connected":
if collection, ok := v.([]interface{}); ok {
for _, c := range collection {
for nk, nv := range keyValuePairs(c) {
nnv, _ := nv.(map[string]interface{})
_, ok := nnv["connectedTo"]
if !ok {
nnv["connectedTo"] = key
}
kvs[nk] = nv
}
}
}
default:
for nk, nv := range keyValuePairs(v) {
kvs[nk] = nv
}
}
}