将复杂的JSON转换为Golang中的map。

huangapple go评论109阅读模式
英文:

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:

  1. {
  2. "people": [
  3. {
  4. "diffs": [
  5. 77
  6. ],
  7. "original": {
  8. "name": "Nick",
  9. "active": "Active",
  10. "email": "nick@example.com"
  11. },
  12. "id": "21"
  13. }
  14. ]
  15. }

答案1

得分: 2

你可以构建一个递归函数,并使用类型断言切换来将JSON数组断言为多维映射或扁平映射。不幸的是,你的多维映射会很快变得复杂。

我的意思是,当你有一个嵌套的JSON数组(例如上面的"people")时,通常需要映射至少几个维度(例如:map[string]map[string]map[string]string)。

如果你尝试扁平化嵌套的JSON数组,你的键会重叠(即你只能使用"name"键一次)。你可以给键加上标签,例如"name_1":"Nick",但这种解决方案可能不适用于你的用例。

如果你想使用多维路线,这个包可能非常适合你的需求:
http://github.com/Jeffail/gabs

我将给你一个定制的示例,然后是gabs的github页面上的两个示例:

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/Jeffail/gabs"
  5. )
  6. func main() {
  7. jsonS := `{
  8. "people": [
  9. {
  10. "diffs": [
  11. 77
  12. ],
  13. "original": {
  14. "name": "Nick",
  15. "active": "Active",
  16. "email": "nick@example.com"
  17. },
  18. "id": "21"
  19. }
  20. ]
  21. }`
  22. gabsCon, err := gabs.ParseJSON([]byte(jsonS))
  23. if err != nil {
  24. fmt.Println("gabs ParseJSON failed")
  25. }
  26. n1, ok := gabsCon.Path("people.original.name").Data().(string)
  27. if !ok {
  28. fmt.Println("gabs path failed")
  29. }
  30. fmt.Println(n1)
  31. }

这是一个非定制的示例,它会打印出"first"、"second"、"third":

  1. jsonParsed, _ := gabs.ParseJSON([]byte(`{"array":["first", "second", "third"]}`))
  2. // S是Search的缩写
  3. children, _ := jsonParsed.S("array").Children()
  4. for _, child := range children {
  5. fmt.Println(child.Data().(string))
  6. }

另一个示例,它会打印出1、2、3:

  1. jsonParsed, _ := gabs.ParseJSON([]byte(`{"array":[{"value":1}, {"value":2}, {"value":3}]}`))
  2. 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:

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/Jeffail/gabs"
  5. )
  6. func main() {
  7. jsonS := `{
  8. "people": [
  9. {
  10. "diffs": [
  11. 77
  12. ],
  13. "original": {
  14. "name": "Nick",
  15. "active": "Active",
  16. "email": "nick@example.com"
  17. },
  18. "id": "21"
  19. }
  20. ]
  21. }`
  22. gabsCon, err := gabs.ParseJSON([]byte(jsonS))
  23. if err != nil {
  24. fmt.Println("gabs ParseJSON failed")
  25. }
  26. n1, ok := gabsCon.Path("people.original.name").Data().(string)
  27. if !ok {
  28. fmt.Println("gabs path failed")
  29. }
  30. fmt.Println(n1)
  31. }

Here's a non-tailored example, which would print - first, second, third):

  1. jsonParsed, _ := gabs.ParseJSON([]byte(`{"array":[ "first", "second", "third" ]}`))
  2. // S is shorthand for Search
  3. children, _ := jsonParsed.S("array").Children()
  4. for _, child := range children {
  5. fmt.Println(child.Data().(string))
  6. }

And, another example, which would print - 1, 2, 3:

  1. jsonParsed, _ := gabs.ParseJSON([]byte(`{"array":[ {"value":1}, {"value":2}, {"value":3} ]}`))
  2. fmt.Println(jsonParsed.Path("array.value").String())

huangapple
  • 本文由 发表于 2017年8月3日 04:25:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/45470368.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定