graphql-go / graphql

An implementation of GraphQL for Go / Golang
MIT License
9.87k stars 839 forks source link

`Cannot return null for non-nullable field` when a non nullable field has a nil parent type #546

Open remorses opened 4 years ago

remorses commented 4 years ago

The following example uses the schema below

type Query {
    product: Product
}

type Product {
    obj: Nested
}

type Nested {
    field: String!
}
package main

import (
    "encoding/json"
    "fmt"
    "log"

    "github.com/graphql-go/graphql"
)

var productType = graphql.NewObject(
    graphql.ObjectConfig{
        Name: "Product",
        Fields: graphql.Fields{
            "obj": &graphql.Field{
                Type: graphql.NewObject(
                    graphql.ObjectConfig{
                        Name: "Nested",
                        Fields: graphql.Fields{
                            "field": &graphql.Field{
                                Type: graphql.NewNonNull(graphql.String),
                            },
                        },
                    },
                ),
            },
        },
    },
)

type Product struct {
    Obj map[string]interface{} `json:"obj"`
}

func main() {
    // Schema
    fields := graphql.Fields{
        "product": &graphql.Field{
            Type: productType,
            Resolve: func(p graphql.ResolveParams) (interface{}, error) {
                return Product{Obj: nil}, nil
            },
        },
    }
    schemaConfig := graphql.SchemaConfig{Query: graphql.NewObject(graphql.ObjectConfig{Name: "Query", Fields: fields})}
    schema, err := graphql.NewSchema(schemaConfig)
    if err != nil {
        log.Fatalf("failed to create new schema, error: %v", err)
    }

    // Query
    query := `
        query {
            product {
                obj {
                    field
                }
            }
        }
    `
    params := graphql.Params{Schema: schema, RequestString: query}
    r := graphql.Do(params)
    if len(r.Errors) > 0 {
        log.Fatalf("failed to execute graphql operation, errors: %+v", r.Errors)
    }
    rJSON, _ := json.Marshal(r)
    fmt.Printf("%s \n", rJSON) // {“data”:{“hello”:”world”}}
}

The query should simply return {"product": {"obj": null}}, instead it gives the error

Cannot return null for non-nullable field Nested.nested.
remorses commented 4 years ago

This problem can be temporarily be fixed using interface{} types inside returned structs, it seems that graphql-go treats the interface{} nil differently from others

alimoli commented 4 years ago

Maybe is the same behaviour I have just described here https://github.com/graphql-go/graphql/issues/553 ?