Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make null value configurable, to allow undefined #1298

Closed
caub opened this issue Mar 23, 2018 · 8 comments
Closed

Make null value configurable, to allow undefined #1298

caub opened this issue Mar 23, 2018 · 8 comments

Comments

@caub
Copy link

caub commented Mar 23, 2018

undefined is practical in JS for destructuring default, so it would be great to allow graphql to avoid converting undefined to null

I see some return null or return Promise.resovle(null) frequently in the sources, how about using a NULL configuration variable, defaulting to null

@leebyron
Copy link
Contributor

I'm afraid I don't understand what you're asking for. Could you point out where you're seeing this? Perhaps some example code or a gist which shows what you expect vs what actually happens?

@caub
Copy link
Author

caub commented Mar 29, 2018

Sorry, so here's an example https://runkit.com/caub/5abd4916eef72b00127e27af

first case: foos is undefined, it's converted to null by graphql

seconds case, inner fields are filled with null

I'd be interested to keep undefined undefined

similar discussion: brianc/node-postgres#1274 (where it ends up keeping null though, but I've hope)

code const { graphql, GraphQLObjectType: ObjectType, GraphQLNonNull: NonNull, GraphQLID: ID, GraphQLString: String, GraphQLList: List, GraphQLSchema: Schema, } = require('graphql');

const Foo = new ObjectType({
name: 'Foo',
fields: {
id: { type: new NonNull(ID) },
name: { type: String },
tags: { type: new List(String) },
},
});

const QueryType = new ObjectType({
name: 'Query',
fields: {
foos: {
type: new List(Foo),
args: {},
resolve: (_, args) => getFoos(args),
},
},
});
const schema = new Schema({
query: QueryType,
});
const gql = (source, variableValues) =>
graphql({
schema,
source,
variableValues,
});

let getFoos = () => undefined;

const {data: {foos}} = await gql({ foos{id, name, tags} });

console.log(foos);

getFoos = () => [{id: '1', name: 'foo1'}, {id: '2'}];

const {data: {foos: foos2}} = await gql({ foos{id, name, tags} });

console.log(foos2);

@leebyron
Copy link
Contributor

Thanks for this extra info. This makes way more sense now.

Unfortunately this isn't something GraphQL.js would consider adding since it breaks some of the core constraints of the spec - which is that you will get a field in the result for every field you ask for in the query. Because of how JSON serializes data, undefined values imply removal of fields, which breaks this core constraint.

JavaScript is also a bit strange in this respect, since most languages do not have a concept of a runtime value for undefined. Since GraphQL.js seeks to be a reference implementation for other GraphQL libraries built in other languages, it's important to remain close to the spec.

In this way, null and undefined actually have special meaning to GraphQL results outside of typical results. null means that the field requested is not available (either due to being non-existent or from an error) while undefined (or absent from response) means that the field was not requested.

To preserve the differences between null and undefined values as typical values rather than special meaning - perhaps because either you intend to translate to a transport mechanism different from JSON where undefined values are preserved (is there such a thing?) or you don't intend to send the results over the network at all - then I would suggest taking a look at some of the libraries that offer resolver middleware to replace undefined with a different placeholder value.

@cphoover
Copy link

cphoover commented Dec 7, 2018

In your client could you just trim the null values to allow for defaults.

This library appears to do that:

https://www.npmjs.com/package/clean-deep

@caub
Copy link
Author

caub commented Dec 8, 2018

undefined (from server-side) also reduces JSON responses size

@Hossein-s
Copy link

Hossein-s commented May 9, 2019

In this way, null and undefined actually have special meaning to GraphQL results outside of typical results. null means that the field requested is not available (either due to being non-existent or from an error) while undefined (or absent from response) means that the field was not requested.

It's common schenario to have fields that are omittable, not nullable. for example when you have password field in the update mutation, it can be omitted (in case user don't want to update password).
But null is a value, if I have a date field for user expiry and I don't set it for some users, I use null.
They are different things. I don't call it undefined in js words. In C# that has strong type system, there's Delta class (in OData library) for such schenarios.

Currently I use nullable notation for omittable inputs and tell client developer to send undefined, that doesn't feel so good :-\

Is there any alternative way of handling this?

@Hossein-s
Copy link

@leebyron Don't yout think that there should be something for achiving what we were doing with REST patch method in graphql? It's very common thing in APIs. 😞

@ndelvalle
Copy link

If reducing the JSON response size is the objective an interesting approach would be to use graphql-crunch.
In my case, I had a lot of duplicated objects with null attributes on it, I wanted to avoid sending them in the response to reduce the JSON size.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants