将复杂的JSON转换为Golang中的映射

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"
        }
    ]
}

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