英文:
Convert complex JSON to map in Golang
问题
如何将复杂的JSON对象转换为具有正确类型的映射(map)在golang中。我是否必须像典型的Golang方式那样创建一个包含我知道将出现的字段的结构体,还是有一种通用的方法可以获取所有正确类型的字段?
以下是我想要转换为映射的JSON示例:
{
"people": [
{
"diffs": [
77
],
"original": {
"name": "Nick",
"active": "Active",
"email": "nick@example.com"
},
"id": "21"
}
]
}
英文:
How can I convert a complex JSON object to a map with all the right types in golang. Do I absolutely have to do the typical Golang thing where I create a struct with the fields that I know will be present or is there a generalized way of getting the fields in all the right types?
Here is an example of a JSON that I want to turn into a map:
{
"people": [
{
"diffs": [
77
],
"original": {
"name": "Nick",
"active": "Active",
"email": "nick@example.com"
},
"id": "21"
}
]
}
答案1
得分: 2
你可以构建一个递归函数,并使用类型断言切换来将JSON数组断言为多维映射或扁平映射。不幸的是,你的多维映射会很快变得复杂。
我的意思是,当你有一个嵌套的JSON数组(例如上面的"people")时,通常需要映射至少几个维度(例如:map[string]map[string]map[string]string)。
如果你尝试扁平化嵌套的JSON数组,你的键会重叠(即你只能使用"name"键一次)。你可以给键加上标签,例如"name_1":"Nick",但这种解决方案可能不适用于你的用例。
如果你想使用多维路线,这个包可能非常适合你的需求:
http://github.com/Jeffail/gabs
我将给你一个定制的示例,然后是gabs的github页面上的两个示例:
package main
import (
"fmt"
"github.com/Jeffail/gabs"
)
func main() {
jsonS := `{
"people": [
{
"diffs": [
77
],
"original": {
"name": "Nick",
"active": "Active",
"email": "nick@example.com"
},
"id": "21"
}
]
}`
gabsCon, err := gabs.ParseJSON([]byte(jsonS))
if err != nil {
fmt.Println("gabs ParseJSON failed")
}
n1, ok := gabsCon.Path("people.original.name").Data().(string)
if !ok {
fmt.Println("gabs path failed")
}
fmt.Println(n1)
}
这是一个非定制的示例,它会打印出"first"、"second"、"third":
jsonParsed, _ := gabs.ParseJSON([]byte(`{"array":["first", "second", "third"]}`))
// S是Search的缩写
children, _ := jsonParsed.S("array").Children()
for _, child := range children {
fmt.Println(child.Data().(string))
}
另一个示例,它会打印出1、2、3:
jsonParsed, _ := gabs.ParseJSON([]byte(`{"array":[{"value":1}, {"value":2}, {"value":3}]}`))
fmt.Println(jsonParsed.Path("array.value").String())
英文:
You could build a recursive function with a type assertion switch to type assert the JSON array into a multi-dimensional map or a flattened map. Unfortunately, your multi-dimensional map is going to get complicated really quickly.
What I mean is, you often need to map at least a few dimensions (for example: map[string]map[string]map[string]string), when you've got a nested JSON array such as "people" above.
If you tried to flatten a nested JSON array, your keys would end up overlapping (i.e. you can only use the "name" key once). You could tag the keys - something like "name_1" : "Nick", but this solution may not work for your use case.
If you want to go the multi-dimensional route, this package may work well for your needs:
http://github.com/Jeffail/gabs
I'll give you a tailored example, and then two examples from the link to gabs's github page:
package main
import (
"fmt"
"github.com/Jeffail/gabs"
)
func main() {
jsonS := `{
"people": [
{
"diffs": [
77
],
"original": {
"name": "Nick",
"active": "Active",
"email": "nick@example.com"
},
"id": "21"
}
]
}`
gabsCon, err := gabs.ParseJSON([]byte(jsonS))
if err != nil {
fmt.Println("gabs ParseJSON failed")
}
n1, ok := gabsCon.Path("people.original.name").Data().(string)
if !ok {
fmt.Println("gabs path failed")
}
fmt.Println(n1)
}
Here's a non-tailored example, which would print - first, second, third):
jsonParsed, _ := gabs.ParseJSON([]byte(`{"array":[ "first", "second", "third" ]}`))
// S is shorthand for Search
children, _ := jsonParsed.S("array").Children()
for _, child := range children {
fmt.Println(child.Data().(string))
}
And, another example, which would print - 1, 2, 3:
jsonParsed, _ := gabs.ParseJSON([]byte(`{"array":[ {"value":1}, {"value":2}, {"value":3} ]}`))
fmt.Println(jsonParsed.Path("array.value").String())
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论