Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I create this this JSON object?

Tags:

json

go

{
  "query": {
    "query_string": {
      "query": "<query string>"
    }
  }
}

The API I'm using requires that I send my queries in this format. I've been trying to find a way to to create this using maps but I keep getting errors and haven't been able to find any solutions online.

Edit: I found a way to do it, is there a better way?

    test := map[string]map[string]map[string]string {
        "query": map[string]map[string]string {
            "query_string": map[string]string{
                "query": query,
             },
        },
    }
like image 284
devinov Avatar asked Dec 09 '15 18:12

devinov


2 Answers

In Go you can unmarshal into a variety of different structures. The most ambiguous being an interface{}. I recommend against that though as you forgo the opportunity to have any real type safety. The other extreme is to use structs, for your example json they would look like this;

type Wrapper struct {
    Query Query `json:"query"`
}

type Query struct {
    QueryString QueryString `json:"query_string"`
}

type QueryString struct {
     Query string `json:"query"`
}

Something in the middle, given you example json would be a map[string]map[string]map[string]. Check out the example here if you don't know how to make use of the encoding/json package. https://golang.org/pkg/encoding/json/#example_Unmarshal

It's pretty straight forward, if you have your input in a []byte and then you instantiate the type you want to unmarshal it into you can just call json.Unmarhsal(jsonBytes, &ThingToUnmarshalInto)

EDIT: based on hobbs' comment it appears you're actually trying to make that json to send to the server. In which case, use the structs above. The example supplied in the other answer demonstrates everything you need. Everything is pretty much the same as I described above except you're calling json.Marshal with an instance of what you want to be turned in to a json string, rather than taking the json string as a []byte and passing it into unmarshal to get a struct. I mistakenly thought you were receiving that json, not trying to form it.

like image 85
evanmcdonnal Avatar answered Nov 15 '22 04:11

evanmcdonnal


Here's an example on Play using both the map way and the struct way.

As you can see, the map form is less code in general and more clear if you need to send one off requests like this.

Struct form will tend to be more performant and possibly more clear if there are a lot of nested or shared types in your requests. If you end up going the struct route, you would likely want something that resembles evanmcdonnal's answer. I used anonymous structs here for brevity.

package main

import "encoding/json"
import "log"

type M map[string]interface{}

type Query struct {
    Query struct {
        QueryString struct {
            Query string `json:"query"`
        } `json:"query_string"`
    } `json:"query"`
}

func main() {
    b, err := json.Marshal(M{"query": M{"query_string": M{"query": "query goes here"}}})
    if err != nil {
        log.Fatalln(err)
    }
    log.Println("   As Map:", string(b))


    var q Query
    q.Query.QueryString.Query = "query in a struct"
    b, err = json.Marshal(q)
    if err != nil {
        log.Fatalln(err)
    }
    log.Println("As Struct:", string(b))
}
like image 30
David Budworth Avatar answered Nov 15 '22 05:11

David Budworth