gpt4 book ai didi

json - 获取一个 JSON 字符串,将其解码为 map[string]interface{},编辑并将其编码为 []byte 似乎比应该的更复杂

转载 作者:IT王子 更新时间:2023-10-29 01:11:13 24 4
gpt4 key购买 nike

我正在做非常基本的 JSON 操作来学习一些 Go,它有效,除了一件事似乎不对,我必须编写分配 .(map[string]interface{}).([]interface{}) 访问 JSON 中的条目,尤其是当它们是 child 的 child 等时。

参见此处(也在 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 .


最简洁的方法是创建预定义类型(结构 struct)来模拟您的 JSON,并解码为该类型的值,您可以使用 Selectors 简单地引用元素。 (对于 struct 类型)和 Index expressions (对于 map 和 slice )。

但是,如果您的输入不是预定义的结构,我建议您使用以下 2 个辅助函数:get()set()。第一个访问(返回)任意路径指定的任意元素(string 映射键列表和/或 int slice 索引),第二个更改(设置)由任意路径指定的值(这些辅助函数的实现在答案的末尾)。

您只需在您的项目/应用中包含这 2 个函数一次。

现在使用这些助手,您想要完成的任务变得如此简单(就像 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() 的实现如下。注意:省略检查路径是否有效。此实现使用 Type switches :

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 - 获取一个 JSON 字符串,将其解码为 map[string]interface{},编辑并将其编码为 []byte 似乎比应该的更复杂,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28877512/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com