Making Graphql input where input can take different types
Asked Answered
H

1

9

I want to create mutation apis where input can be of different types, something like interface which we have in types. I know that we cannot have interface in input types, I want to know how we can support multiple input types in just one input. To explain the problem, I am using a dummy example:

input CreateCatInput{
  id: String
  name: String
}

input CreateDogInput{
  id: String
  name: String
  breed: String
}

input CreateElephantInput{
  id: String
  name: String
  weight: String
}

Now, if we want to write apis for it, I will have to write api for each type

createCat(input: CreateCatInput!)
createDog(input: CreateDogInput!)
createElephant(input: CreateElephantInput!)

The problem I have with this approach is:

  1. I will have to write a lot of apis, assume if I support 20 types of animal then I will have to write 20 create apis. But I don't like this many apis for the users, I want that the user should see very few apis.
  2. Assume we support 20 types of animals, how will the user know what all animals are supported, they will have to see all the apis we support in the API explorer.

The solution I am looking for is that I have only one api :

  createAnimal(input: CreateAnimalInput!)

Since interface support is not there currently, how companies are implementing input which can be of multiple types? How can I define the input such that I can only give only one input in the api ?

I have read this suggestion, but it involves defining annotations, I am currently trying it. I want to see how other people are solving this issue.

Edit: Looks like a lot of work is now done on this topic https://github.com/graphql/graphql-spec/pull/733 and the feature will be available soon.

Hearthside answered 2/2, 2020 at 7:28 Comment(0)
G
12

Input union type can solve your problem but unfortunately it is not supported now . However , the good news is that there is already a RFC for this feature which means it is possible it will be included in the next GraphQL specification release.

At this moment , I will model it using the nested input with an enum to differentiate which animal type the user is actually want to create. Somethings look like :

input CreateAnimalInput{
  id:   String
  name: String
  animalType :AnimalType!
  dogParam   : CreateDogInput
  elephantParam : CreateElephantInput
}

enum AnimalType{
  DOG
  ELEPHANT
}

input CreateDogInput{
  breed: String
}

input CreateElephantInput{
  weight: String
}

createAnimal(input: CreateAnimalInput!)

If an animalType is set to DOG , only values in the dogParam field will be considered and other animal parameter fields will be ignored.


Update on Nov-2022 : Input union type is superseded by OneOf input type.

Greenstone answered 3/2, 2020 at 4:19 Comment(4)
Hey @Ken Chan, Thanks for answering the question. Since union support is not there a developer can only use either the composition way you discussed or make separate entity for dog/cat.Hearthside
@Key Chan. Thanks for this detailed answer. I also had this nested solution in mind, But you explained it very nicely. The only problem I see here is that the update api will also be nested, In one update api we will be updating the dog and cat both. Is there a other way too for update ?Hearthside
The update schema will look exactly the name. So @Key Chan no need to add the update part.Hearthside
Just to update the current status. The oringal RFC link, links back to this thread, but the actual link is here. However, this has been surplanted by the oneof input type, whichc can be viewed here.Blanks

© 2022 - 2024 — McMap. All rights reserved.