graphql-go / graphql-go/graphql

Nulls, zero values and defaults in results

Open
#449 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Go
Stars
10.1k
Forks
845
PR merge metrics
No merged PRs in 30d

Description

Let's say I have an object declared with a non-null boolean like this:

```go
graphql.NewObject(graphql.ObjectConfig{
Name: "MyQuery",
Fields: graphql.Fields{"featured": &graphql.Field{
Type: graphql.NewNonNull(graphql.Boolean),
},
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
return map[string]interface{}{}
},
})
```

What happens now is that the query will _fail_ because the output data is missing a required field: `Cannot return null for non-nullable field MyQuery.featured.`

This doesn't quite gel with with Go's concept of zero types. In Go, an uninitialized boolean is false, so it is not null. In my opinion, it would make more sense here to not error on missing primitives, but coerce them to their default value.

We can remedy by using a resolver, but it's obviously not ideal:

```go
// ...
Fields: graphql.Fields{"featured": &graphql.Field{
Type: graphql.NewNonNull(graphql.Boolean),
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
if s, ok := p.Source.(bool); ok {
return s, nil
}
return false, nil
},
},
```

I was a little dismayed that `NewNonNull` and `NonNull` are magical and cannot be implemented by the user, since they're just data. Null checks on output happen in `executor.go`, `completeValue()`, which explicitly looks for `NonNull` and does a null check on the value. That means you can't implement a wrapper such as:

Perhaps it might make sense to add a new mode, e.g. a default:

```go
// ...
Fields: graphql.Fields{"featured": &graphql.Field{
Type: graphql.NewNonNull(graphql.WithDefault(graphql.Boolean, false)),
},
```

I expected types to implement their validation logic, so that I could implement my own type wrapper, but I can't — it's not composable.

An easier change would be to add explicit support for defaults:

```go
// ...
Fields: graphql.Fields{"featured": &graphql.Field{
Type: graphql.NewNonNull(graphql.Boolean),
DefaultValue: false,
},
```

Thoughts? @chris-ramon?

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.