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

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

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())

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:

确定