您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

取一个JSON字符串,将其解组到map [string] interface {},进行编辑,然后将其编组为[] byte似乎要复杂得多,

取一个JSON字符串,将其解组到map [string] interface {},进行编辑,然后将其编组为[] byte似乎要复杂得多,

我优化并改进了以下解决方案,并将其作为库发布在这里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"))

输出

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]
            }
        }
    }
}
其他 2022/1/1 18:14:19 有419人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶