2

I have a GraphQL query that looks like this:

{
    actor {
      entitySearch(query: "name LIKE 'SOME_NAME'") {
        results {
          entities {
            guid
          }
        }
      }
    }
  }

I can't figure out how to create the Go struct to hold the returned data. The only thing I care about is the guid field that gets returned.

This clearly doesn't work:

type graphQlResponse struct {
    guid string
}

Any help? Or is there a way I can simply get the guid and store it in a string without a struct?

Here is the whole code. I don't get an error, but guid is an empty string:

package main

import (
    "context"
    "fmt"
    "log"

    "github.com/machinebox/graphql"
)

func main() {

    type graphQlResponse struct {
        guid string
    }

    // create a client (safe to share across requests)
    client := graphql.NewClient("GraphQL EndPoint")

    // make a request
    req := graphql.NewRequest(`
    {
        actor {
          entitySearch(query: "name LIKE 'SOME_NAME'") {
            results {
              entities {
                guid
              }
            }
          }
        }
      }
`)

    // set any variables
    //req.Var("key", "value")

    // set header fields
    //req.Header.Set("Cache-Control", "no-cache")
    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("API-Key", "KEY_HERE")

    // define a Context for the request
    ctx := context.Background()

    // run it and capture the response
    var respData graphQlResponse
    if err := client.Run(ctx, req, &respData); err != nil {
        log.Fatal(err)
    }

    fmt.Println(respData.guid)
}
6
  • The quoted data is not valid JSON. If you have a library that will parse that data format, what library is it? Commented Sep 19, 2019 at 19:15
  • It's a GraphQL query that returns json. The query itself I guess is not proper json, but it works in a GraphQL explorer. Commented Sep 19, 2019 at 19:17
  • So what does the returned JSON actually look like? And when you say "This clearly doesn't work", can you clarify how it doesn't work? Do you get an error or what? I'm guessing one issue is that your guid field is unexported (starts with a lowercase letter), but without any example data, example code, or clear problem statement, it's hard to offer much advice. Commented Sep 19, 2019 at 19:18
  • After the edit I'd still guess it's because guid is unexported. But again, without a sample of the returned JSON data, I can't rule out additional issues that might cause it not to work as desired after that's fixed. Commented Sep 19, 2019 at 19:39
  • I can't SEE the returned data because I can't figure out how to store it. Hence most of the problem. Commented Sep 19, 2019 at 19:58

2 Answers 2

2

In GraphQL, the shape of the returned JSON will match the shape of the GraphQL query: you will have a "data" field, which will have an "actor" child, which will contain "entitySearch", and so on. The library you're calling is in fact pretty minimal. Given the conventional HTTP transport format, it uses ordinary encoding/json decoding to decode the response. Whatever structure you provide needs to be able to unmarshal the "data" field.

This means that you need to create a nested set of structures that mirrors the JSON format, which in turn mirrors your GraphQL query:

type Entity struct {
    Guid string `json:"guid"`
}
type Result struct {
    Entities Entity `json:"entities"`
}
type EntitySearch struct {
    Results Result `json:"results"`
}
type Actor struct {
    EntitySearch EntitySearch `json:"entitySearch"`
}
type Response struct {
    Actor Actor `json:"actor"`
}

fmt.Println(resp.Actor.EntitySearch.Results.Entities.Guid)

https://play.golang.org/p/ENCIjtfAJif has an example using this structure and an artificial JSON body, though not the library you mention as such.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for taking the time. In your playground you have a string that contains json. I don't have that. I have a graphql api that returns json and I can't figure out how/where to initially store it so that I can test the rest of your example.
When you call client.Run in your code, you need to pass it the outermost structure in this stack.
0

I suggest using a map and the json package.

I am unfamiliar with graphQL so I'll make a regular HTTP request and hope you can use it to make sense of your own issue:

response, err := http.Get("https://example.com")
// error checking code omitted
defer response.Body.Close()

// now we want to read the body, easiest way is with the ioutil package,
// this should work with the graphQL response body assuming it satisfies
// the io.Reader interface. This gets us the response body as a byte slice
body, err := ioutil.ReadAll(response.Body)

// next make a destination map, interface can be used in place of string or int
// if you need multiple types
jsonResult := map[string]string{"uuid": ""}

// finally, we use json.Unmarshal to write our byte slice into the map
err = json.Unmarshal(body, &jsonResult)

// now you can access your UUID
fmt.Println(jsonResult["uuid"])

I assume that a REST response and a graphQL response are similar, if that's not the case let me know what type the request body is and I can help you figure out a better fitting solution.

1 Comment

Thank you. I'll play around with this and comment back when I know more.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.