What's the best way to work with nested JSON structures in Golang?

I would like to work with JSON in Golang, in particular the JSON protocol with elastic search.

JSON is deeply nested (this is a simple request):

{
    "query": {
        "filtered": {
            "query": {
                "match_all": {}
            },
            "filter": {
                "and": [
                    {
                        "range" : {
                            "b" : { 
                                "from" : 4, 
                                "to" : "8"
                            }
                        },
                    },
                    {
                        "term": {
                            "a": "john"
                        }
                    }
                ]
            }
        }
    }
}

      

This structure easily maps to Ruby's own data structure.

But with Golang, it seems like you have to define the exact structure with the structures (maybe generate them programmatically from a JSON source).

However, things like arrays of different "types" of objects in JS require workarounds and custom code. For example, "and" is the key in the JSON example. ( http://mattyjwilliams.blogspot.co.uk/2013/01/using-go-to-unmarshal-json-lists-with.html ).

Is there a better way to work with JSON in Golang?

+7


source to share


4 answers


If you decide to go the structure path, consider this example:

{"data": {"children": [
  {"data": {
    "title": "The Go homepage",
    "url": "http://golang.org/"
  }},
  ...
]}}

// -----------

type Item struct {
    Title string
    URL   string
}

type Response struct {
    Data struct {
        Children []struct {
            Data Item
        }
    }
}

      



Source: http://talks.golang.org/2012/10things.slide#4

+3


source


One option is to use the gabs library: https://github.com/Jeffail/gabs

This is useful for parsing and generating complex json structures.

This is an example of nested json generation from the README:



jsonObj := gabs.New()
// or gabs.Consume(jsonObject) to work on an existing map[string]interface{}

jsonObj.Set(10, "outter", "inner", "value")
jsonObj.SetP(20, "outter.inner.value2")
jsonObj.Set(30, "outter", "inner2", "value3")

      

This will print:

{"outter":{"inner":{"value":10,"value2":20},"inner2":{"value3":30}}}

      

+2


source


For native golang use map[string]interface{}

or define a struct. Another way to easily access the json object could be JsonPath or Jason

+1


source


Based on this article, https://medium.com/@xcoulon/nested-structs-in-golang-2c750403a007 , you have to define json tags for each field, then you can use nested structure
Example below, you can insert it into playground pad and check it out.

package main

import (
    "encoding/json"
    "fmt"
)
type Config struct {
    Server struct {
        Host string 'json:"host"'
        Port string 'json:"port"'
        } 'json:"server"'
    Postgres struct {
        Host     string 'json:"host"'
        User     string 'json:"user"'
        Password string 'json:"password"'
        DB       string 'json:"db"'
    } 'json:"database"'
}

func main() {
    jsonConfig := []byte('{
        "server":{
            "host":"localhost",
            "port":"8080"},
        "database":{
            "host":"localhost",
            "user":"db_user",
            "password":"supersecret",
            "db":"my_db"}}')
    var config Config
    err := json.Unmarshal(jsonConfig, &config)
    if err != nil {
        panic(err)
    }
    fmt.Printf("Config: %+v\n", config)
}

      

0


source







All Articles