Graphql: Custom deserialization of input objects

Created on 19 Feb 2019  路  1Comment  路  Source: graphql-go/graphql

From what I can tell, the only format of an input object is a map[string]interface{}. So if you have something like this:

schema := graphql.NewSchema(graphql.SchemaConfig{
  Query: graphql.NewObject(graphql.ObjectConfig{
    Name: "RootQuery",
    Fields: graphql.Fields{
      "search": &graphql.Field{
        Type: builder.MustFindType("Result"),
        Args: graphql.FieldConfigArgument{
          "query": &graphql.ArgumentConfig{
            Type: graphql.NewInputObject(graphql.InputObjectConfig{
              Name: "Query",
              Fields: graphql.InputObjectConfigFieldMap{
                // ...
              },
            })
          },
        },
        Resolve: func(p graphql.ResolveParams) (interface{}, error) {
          // ...
        },
      },
    },
  }),
})

In the resolver, p.Args["query"] always gives you a map[string]interface{}. So if you have a struct like this that you want to map the input to:

type Query struct {
  Text      string `json:"text"`
  DateRange DateRange `json:"dateRange"`  
}

Then it sees you have to go via JSON marshaling, with some unperformant logic like this:

Resolve: func(p graphql.ResolveParams) (interface{}, error) {
  if p.Args["query"] == nil {
    return nil, errors.New("query must be specified")
  }
  b, err := json.Marshal(p.Args["query"])
  if err != nil {
    return nil, err
  }
  var query Query
  if err = json.Unmarshal(b, &query); err != nil {
    return nil, err
  }
  return performQuery(query)
}

Any plans to support custom deserializers for inputs?

Most helpful comment

I've been doing stuff like this:

Resolve: func(p graphql.ResolveParams) (interface{}, error) {
  queryMap := p.Args["query"].(map[string]interface{})

  query := Query{
    Foo: queryMap["foo"],
    Bar: queryMap["bar"],
  }

  return performQuery(query)
}

However, this gets really messy once you get to multiple levels of nesting. I'd also love an easier way to deserialize the args right into a struct (similar to how struct serialization is already done in the opposite direction).

>All comments

I've been doing stuff like this:

Resolve: func(p graphql.ResolveParams) (interface{}, error) {
  queryMap := p.Args["query"].(map[string]interface{})

  query := Query{
    Foo: queryMap["foo"],
    Bar: queryMap["bar"],
  }

  return performQuery(query)
}

However, this gets really messy once you get to multiple levels of nesting. I'd also love an easier way to deserialize the args right into a struct (similar to how struct serialization is already done in the opposite direction).

Was this page helpful?
0 / 5 - 0 ratings

Related issues

tobyjsullivan picture tobyjsullivan  路  5Comments

FrontMage picture FrontMage  路  5Comments

yhc44 picture yhc44  路  5Comments

schaze picture schaze  路  4Comments

januszm picture januszm  路  6Comments