shurcooL / githubv4

Package githubv4 is a client library for accessing GitHub GraphQL API v4 (https://docs.github.com/en/graphql).
MIT License
1.11k stars 89 forks source link

QQ on generating proper struct #55

Closed atmosx closed 4 years ago

atmosx commented 4 years ago

Hello,

I'm trying to convert the following GraphQL expression to Golang struct:

query{
  search(first: 100, type: REPOSITORY, query: "topic:golang org:google") {
    pageInfo {
      hasNextPage
      endCursor
      }
    repos: edges {
      repo: node {
        ... on Repository {
          name
          url
          id
        }
      }
    }
  }
}

I came up with something like this:

package main

import (
    "context"

    "fmt"

    "github.com/shurcooL/githubv4"
    "golang.org/x/oauth2"
)

var q struct {
    Search struct {
        PageInfo struct {
            HasNextPage bool
            EndCursor   githubv4.String
        }
        Repos []struct {
            Repo []struct {
                Repository struct {
                    Name githubv4.String
                } `graphql:"... on Repository"`
            } `graphql:"repo: node"`
        } `graphql:"repos: edges"`
    } `graphql:"search(first: 3, type: REPOSITORY, query: \"topic:golang org:google\")"`
}

func main() {
    token := "123"
    ctx := context.Background()
    ts := oauth2.StaticTokenSource(
        &oauth2.Token{AccessToken: token},
    )
    tc := oauth2.NewClient(ctx, ts)

    client := githubv4.NewClient(tc)
    err := client.Query(context.Background(), &q, nil)
    if err != nil {
        fmt.Println(err)
    }
    fmt.Println(q.Search.Repos)
}

However, I'm getting back an empty struct:

$ go run main.go
struct field for "name" doesn't exist in any of 1 places to unmarshal
[{[]}]

Ideas, thoughts?

Thank you for your time & Happy new year!

P.

dmitshur commented 4 years ago

Hi @atmosx,

Thanks for providing the exact GraphQL query and the Go code you tried, it made investigating this very easy.

The problem is here:

-Repo []struct {
+Repo struct {

It is because the `graphql:"repo: node"` field corresponds to a SearchResultItemEdge.node, which a single SearchResultItem, not a list.

It's unfortunate the error message is not more helpful in spotting where the problem is. I have added a comment in https://github.com/shurcooL/graphql/issues/46#issuecomment-570762336 to investigate if it's possible to improve that.

dmitshur commented 4 years ago

Slightly off topic, I want to point out you could simplify that query by using the nodes field directly (since the only field in SearchResultItemEdge being used is node):

nodes {
    ... on Repository {
        name
    }
}

Its Go code equivalent:

Repos []struct {
    Repository struct {
        Name githubv4.String
    } `graphql:"... on Repository"`
} `graphql:"nodes"`
atmosx commented 4 years ago

Thanks @dmitshur for the prompt reply and simplified version of the query!

I'm closing the issue as it is solved.