我正在做非常基本的JSON操作来学习Go语言,并且可以正常工作,除非似乎有一件事情,我必须编写JSON的分配.(map[string]interface{})
并.([]interface{})
访问JSON中的条目,尤其是当它们是孩子的孩子时,等等。
参见此处(也在Go Playground上:https :
//play.golang.org/p/Wd-pzHqTsU):
package main
import (
"fmt"
"encoding/json"
)
func main() {
JSON := []byte(`{"key1":"val1","key2":{"c1key1":"c1val1"},"key3":[{"c2key1":{"c3key1":"c3val1"}}]}`)
fmt.Printf("%s\n", JSON)
var d map[string]interface{}
json.Unmarshal(JSON, &d)
fmt.Println(d["key3"].([]interface{})[0].(map[string]interface{})["c2key1"].(map[string]interface{})["c3key1"])
d["key3"].([]interface{})[0].(map[string]interface{})["c2key1"].(map[string]interface{})["c3key1"] = "change1"
fmt.Println(d["key3"].([]interface{})[0].(map[string]interface{})["c2key1"].(map[string]interface{})["c3key1"])
JSON, _ = json.Marshal(d)
fmt.Printf("%s\n", JSON)
}
哪个返回:
{"key1":"val1","key2":{"c1key1":"c1val1"},"key3":[{"c2key1":{"c3key1":"c3val1"}}]}
c3val1
change1
{"key1":"val1","key2":{"c1key1":"c1val1"},"key3":[{"c2key1":{"c3key1":"change1"}}]}
现在,在Python中,我直接访问键/值,而不是定义每次访问的类型,而不是fmt.Println(d["key3"].([]interface{})[0].(map[string]interface{})["c2key1"].(map[string]interface{})["c3key1"])
您print d["key3"][0]["c2key1"]["c3key1"]
Python示例:
import json
JSON = '{"key3": [{"c2key1": {"c3key1": "c3val1"}}], "key2": {"c1key1": "c1val1"}, "key1": "val1"}'
print JSON
d = json.loads(JSON)
print d["key3"][0]["c2key1"]["c3key1"]
d["key3"][0]["c2key1"]["c3key1"] = "change1"
print d["key3"][0]["c2key1"]["c3key1"]
JSON = json.dumps(d)
print JSON
那么我在Go中这样做正确吗?如果是这样,此设计的原因是什么?否则,我该怎么办?
前言:
我优化和改进了以下解决方案,并将其作为库发布在这里:github.com/icza/dyno
。
最干净的html" target="_blank">方法是创建struct
对JSON建模的预定义类型(结构),并解组为该类型的值,并且您可以使用Selectors(用于struct
类型)和Index表达式(用于地图和切片)简单地引用元素。
但是,如果您的输入不是预定义的结构,则建议您使用以下2个辅助函数:get()
和set()
。第一个访问(返回)由任意路径(string
映射键和/或int
切片索引的列表)指定的任意元素,第二个访问(返回)由任意路径指定的值(这些帮助函数的实现在最后)答案)。
您只需在项目/应用程序中包含这两个功能。
现在,使用这些帮助器,您想要执行的任务变得非常简单(就像python解决方案一样):
fmt.Println(get(d, "key3", 0, "c2key1", "c3key1"))
set("NEWVALUE", d, "key3", 0, "c2key1", "c3key1")
fmt.Println(get(d, "key3", 0, "c2key1", "c3key1"))
输出:
change1
NEWVALUE
在Go Playground上尝试修改后的应用程序。
注意-进一步简化:
您甚至可以将路径保存在变量中,然后重复使用以进一步简化上面的代码:
path := []interface{}{"key3", 0, "c2key1", "c3key1"}
fmt.Println(get(d, path...))
set("NEWVALUE", d, path...)
fmt.Println(get(d, path...))
和的实现get()
,并set()
在下面。注意:检查路径是否有效被省略。此实现使用类型开关:
func get(m interface{}, path ...interface{}) interface{} {
for _, p := range path {
switch idx := p.(type) {
case string:
m = m.(map[string]interface{})[idx]
case int:
m = m.([]interface{})[idx]
}
}
return m
}
func set(v interface{}, m interface{}, path ...interface{}) {
for i, p := range path {
last := i == len(path)-1
switch idx := p.(type) {
case string:
if last {
m.(map[string]interface{})[idx] = v
} else {
m = m.(map[string]interface{})[idx]
}
case int:
if last {
m.([]interface{})[idx] = v
} else {
m = m.([]interface{})[idx]
}
}
}
}
问题内容: 我正在做非常基本的JSON操作来学习Go语言,并且可以正常工作,除非似乎有一件事情,我必须编写JSON的分配并访问JSON中的条目,尤其是当它们是孩子的孩子时,等等。 参见此处(也在Go Playground上:https : //play.golang.org/p/Wd-pzHqTsU): 哪个返回: 现在,在Python中,我直接访问键/值,而不是定义每次访问的类型,而不是您 Py
在这种情况下,调用是否会返回错误? 我想知道部分是出于好奇,部分是考虑我是否需要担心错误检查。
问题内容: 从来源来看,我无法影响我在地图中获得的数据,该地图以表示。 我需要处理所包含的数据,最好是(其中的数据非常适合该处理)。 我还需要从数据中生成键列表,因为这些键是事先未知的。 我可以在网上找到的大多数类似问题或多或少都说这是不可能的,但是如果我的地图是,则表明数据在那里,可读性为。 我该怎么办fmt.Println可以做什么? 问题答案: 处理未知接口的一种安全方法,只需使用fmt.S
问题内容: 我想更改字节数组中的值以在MSB中放入较长的时间戳值。有人可以告诉我最好的方法是什么。我不想一点一点地插入值,我认为这是非常低效的。 我想要的是这样的: 这样是可能的。在此字节数组中编辑/插入值的最佳方法是什么。由于字节是原始数据,我不认为有一些直接的实现可以利用吗? 编辑: 似乎比快,所以用它替换上面的代码。如果有误,请纠正我。 问题答案: 有多种方法可以做到这一点: 使用(最佳选择
问题内容: 说我有以下代码: 在这种情况下,有什么办法可以使调用返回错误? 我想知道,部分原因是出于好奇,另一部分是考虑是否需要担心该错误检查。 问题答案: 由于任何有效值都是有效键,而且也是JSON中的有效值(有关详细信息,请参阅JSON键名中的哪些字符有效/无效?,因此从理论上讲,它不会返回任何错误。 如果发生内存不足错误,则不会返回错误,您的应用将终止并显示错误代码。 由于Go将值存储为其U
问题内容: 我有两个字符串数组键和值 将它们转换为地图的最快方法是什么?我知道我们可以遍历它们。但是,这里有实用程序吗? 问题答案: 比这快吗?