前言:
我优化和改进了以下解决方案,并将其作为库发布在这里:
github.com/icza/dyno。
最干净的方法是创建
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"))输出:
change1NEWVALUE
在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字符串,将其解组到map [string] interface {}中,进行编辑,然后将其编组为[] byte似乎要复杂得多, 取一个JSON字符串,将其解组到map [string] interface {}中,进行编辑,然后将其编组为[] byte似乎要复杂得多,](http://www.mshxw.com/aiimages/31/425818.png)
