GraphQL: Non-nullable array/list
Asked Answered
S

1

69

I'm learning GraphQL now and while walking through tutorial I met behavior that I can't understand. Let's say we have defined type in schema:

type Link {
  id: ID!
  url: String!
  description: String!
  postedBy: User
  votes: [Vote!]!
}

Due to docs votes: [Vote!]! means that that field should be a non-nullable and array itself should be non-nullable too. But just after that author of tutorial shows example of query and for some of links it returns empty array for votes field. Like this:

{
 "url": "youtube.com",
 "votes": []
},
{
 "url": "agar.io",
 "votes": []
}

So my question is: Doesn't "non-nullable" means "empty" in graphQL schema or it's just some kind of wrong behavior of graphQL server (I mean it returns array of nothing without warning that there should be something due to schema).

Thanks!

Sclater answered 16/10, 2017 at 12:36 Comment(2)
May I know the URL of the tutorial you are talking about?Narcotic
Currently GraphQL do not allow to validate array length (github.com/graphql/graphql-js/issues/397).Depravity
D
233

Non-null means exactly what it sounds like -- not null. An empty array is not null -- it's still returning a value.

Here is a summary table:

declaration accepts: | null | []   | [null] | [{foo: 'BAR'}]
------------------------------------------------------------------------
[Vote!]!             | no   | yes  | no     | yes
[Vote]!              | no   | yes  | yes    | yes
[Vote!]              | yes  | yes  | no     | yes
[Vote]               | yes  | yes  | yes    | yes

[Vote!]! means that the field (in this case votes) cannot return null and that it must resolve to an array and that none of the individuals items inside that array can be null. So [] and [{}] and [{foo: 'BAR'}] would all be valid (assuming foo is non-null). However, the following would throw: [{foo: 'BAR'}, null]

[Vote]! means that the field cannot return null, but any individual item in the returned list can be null.

[Vote!] means that the entire field can be null, but if it does return a value, it needs to be an array and each item in that array cannot be null.

[Vote] means that the entire field can be null, but if it does return a value, it needs to be an array. However, any member of the array may also be null.

If you need to verify whether an array is empty, you have to do so within your resolver logic. If you want GraphQL to still throw when an array is empty, just have your resolver return a rejected Promise.

For more information your can read the list and non-null section of the GraphQL introduction or take a look at the spec.

Derward answered 16/10, 2017 at 13:46 Comment(5)
Maybe I was confused because of paragraph in tutorial: "[Episode]! represents an array of Episode objects. Since it is also non-nullable, you can always expect an array (with zero or more items) when you query the appearsIn field." For some reasons I though if absence of exclamation mark means "zero or more items" so presence of exclamation mark means there should be at least 1 item. Thanks for your answer!Sclater
@daniel-rearden thanks for your precise answer. But what for would I use an array with nulls inside? [] and [null] are pretty similar (no info inside), so why do we need both?Phene
@VladimirAlexiev It could be useful for returning one array element for each requested element (example: request [4, 1, 2, 6] => response [Vote, null, null, Vote])Sancho
I figured there is another reason: to report a particular element as erroneous. Say Vote has a mandatory field, but it's missing or a particular vote: then the error should be propagated and that whole Vote should be nulled out. AND if the array has type [Vote!] then the whole array should be nulled out!Phene
Good point @VladimirAlexiev Errors will propagate differently depending on whether the list element is non-null or not. See this section of the spec for more details.Derward

© 2022 - 2024 — McMap. All rights reserved.