How to map Set -> List #1110
-
Hello! First off, I understand the reasoning for not supporting the automatic mapping of Kotlin Sets to GraphQL List types as per the docs and the various issue/pr conversations around the topic. But I am trying to add graphql to an existing Kotlin project that has a collection of domain objects defined as data classes which heavily use Sets. So I will need some way to do this and its not feasible for me to do this mapping manually. Currently I'm trying to do that by maintaining separate copies of these data classes and mapping all of their properties manually. For example: data class DomainClient(
val firstName: String,
val lastName: String,
// ... many more properties,
val locations: Set<Location> = emptySet()
)
data class Client(
val firstName: String,
val lastName: String,
// ... many more properties,
val locations: List<Location> = emptyList()
)
fun clientFromDomain(c: DomainClient): Client = Client(
firstName = c.firstName,
lastName = c.lastName,
// ... many more properties,
locations = c.locations.toList()
)
@Provider
class ClientsQuery @Inject constructor(
private val clientService: ClientService
) : Query {
fun clients(context: CustomGraphQLContext): List<Client> {
return clientService.getClients(context.user.accountId)
.map { clientFromDomain(it) }
}
} Which is exceedingly yucky given the number of classes/fields I need to map across this project. All I really want is a way to automate this mapping, I don't even necessarily want that reflected in the resulting schema. I'm fine with the schema outputting these fields as a List type, and then serializing/deserializing these fields into Sets behind the scenes as long as I don't have to do it manually. It seems like functionality was introduced to accommodate this workflow as discussed in this issue: #584 but I don't understand how I would greatly appreciate any help on this |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 20 replies
-
Hello 👋
override fun willGenerateGraphQLType(type: KType): GraphQLType? = when (type.classifier) {
Set::class -> GraphQLList.list(GraphQLTypeReference.typeRef(type.getTypeOfFirstArgument().getSimpleName()))
else -> super.willGenerateGraphQLType(type)
}
override fun isValidSuperclass(kClass: KClass<*>): Boolean {
return if(kClass == Set::class) false else super.isValidSuperclass(kClass)
}
val additionalTypes = mutableSetOf(MyClass::class.createType())
val generator = SchemaGenerator(config) // config should use your custom hooks from above
return generator.use {
it.generateSchema(queries, mutations, subscriptions, additionalTypes)
} |
Beta Was this translation helpful? Give feedback.
-
For anyone who got here and was still confused, the example project has the current solution class CustomSchemaGeneratorHooks() : SchemaGeneratorHooks {
override fun willResolveMonad(type: KType): KType = when (type.classifier) {
Set::class -> List::class.createType(type.arguments)
else -> super.willResolveMonad(type)
}
} And then to use this in a spring server, this is also needed from the example project: @Configuration
class GraphQLConfiguration {
@Bean
fun hooks() = CustomSchemaGeneratorHooks()
} |
Beta Was this translation helpful? Give feedback.
Hello 👋
I think the "simplest" way would be to follow the suggestion from #584 with small update -> with latest code you can just pass the additional types to the generator directly.
SchemaGeneratorHooks
Set
types to ensure they get generated