gpt4 book ai didi

kotlin - 如何在带有ktor框架的graphql-kotlin中进行字段级解析器

转载 作者:行者123 更新时间:2023-12-02 13:36:16 28 4
gpt4 key购买 nike

如何使用gaphql-kotlin做场级(非根)解析器?我的代码正常工作(API1Response中的date_range为空,因为当查询中存在date_range时我不知道如何调用第二个解析器函数getAPI2Response())当每个查询分别调用时,因为我有两个带有关注查询名称的暂挂函数,但我想调用基于字段(非根)的两个查询的一个查询的挂起函数。例如,在下面显示的代码(服务)中,如果我的查询是带有字段“name”,“id”,“date_range”的“getAPI1Response”,则graphql应该调用getAPI1Response和getAPI2Response并将其映射到数据模型“API1Response”,因此用户可以使用单个查询来代替触发两个查询。

检查了graphql-kotlin样本中的几个样本,但所有样本都指向我未使用的springboot。

//DATA MODEL

data class API1Response(
val name: String?,
val id: Int?,
val date_range: API2Response?
)

data class API2Response(
val max_date_range: ZonedDateTime?,
val min_date_range: ZonedDateTime?
)
//SERVICE
class Query() {
private val httpClient = HttpClient()

// when query name is "getAPI1Response", this function get triggers
suspend fun getAPI1Response(): API1Response {
// call API 1 and map response to API1Response model.
return resp.content.toInputStream().use {
jackson.readValue(it, API1Response::class.java)
}
}

//// when query name is "getAPI2Response", this function get triggers
suspend fun getAPI2Response(): API2Response {
// call API 2 and map response to API2Response model.
return resp.content.toInputStream().use {
jackson.readValue(it, API2Response::class.java)
}
}
}
// GRAPHQL HANDLER

package com.my.package.graphql

import com.expedia.graphql.SchemaGeneratorConfig
import com.expedia.graphql.TopLevelObject
import com.expedia.graphql.hooks.SchemaGeneratorHooks
import com.expedia.graphql.toSchema
import com.my.package.errors.ErrorType
import com.my.package.http.*
import com.my.package.json.Jackson
import graphql.ExecutionInput
import graphql.GraphQL
import graphql.language.StringValue
import graphql.schema.*
import graphql.schema.idl.SchemaPrinter
import io.ktor.application.ApplicationCall
import io.ktor.application.call
import io.ktor.http.ContentType
import io.ktor.http.HttpStatusCode
import io.ktor.response.respondText
import io.ktor.routing.Route
import io.ktor.routing.get
import io.ktor.routing.post
import java.time.LocalDate
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
import kotlin.reflect.KClass
import kotlin.reflect.KType

class GraphQLHandler(
mutations: List<Any>,
queries: List<Any>
) : Handler {
private val schema = toSchema(
config = SchemaGeneratorConfig(
supportedPackages = listOf("com.my.package"),
hooks = CustomSchemaGeneratorHooks(),
topLevelQueryName = "Query",
topLevelMutationName = "Mutation"
),
mutations = mutations.map { TopLevelObject(it) },
queries = queries.map { TopLevelObject(it) }
)

private val graphQL = GraphQL.newGraphQL(schema).build()

override val path = "/graphql"

override val routes: Route.() -> Unit = {
post {
postQuery(call)
}
}

private suspend fun postQuery(call: ApplicationCall) {
val reqBody = call.receiveJson(Map::class)
val query = reqBody["query"] as? String
if (query == null) {
call.respondError(
HttpStatusCode.BadRequest,
ErrorType.bad_request,
"missing or invalid query field in json"
)
return
}

@Suppress("UNCHECKED_CAST")
val variables = reqBody["variables"] as? Map<String, Any> ?: emptyMap()

handleQuery(call, query, variables)
}

// main function which calls my concern suspend funciton mapping query name to function name
private suspend fun handleQuery(call: ApplicationCall, query: String, variables: Map<String, Any>?) {
val executionInput = ExecutionInput(query, null, call.request.authContext, null, variables)
val result = graphQL.execute(executionInput).toSpecification()
val statusCode = if (result.containsKey("errors")) HttpStatusCode.InternalServerError else HttpStatusCode.OK
call.respondJson(statusCode, result, Jackson.all)
}
}

class CustomSchemaGeneratorHooks : SchemaGeneratorHooks {
override fun willGenerateGraphQLType(type: KType): GraphQLType? = when (type.classifier as? KClass<*>) {
ZonedDateTime::class -> graphqlZonedDateTimeType
LocalDate::class -> graphqlLocalDateType
else -> null
}
}

val graphqlLocalDateType = GraphQLScalarType("LocalDate",
" ISO date format without an offset, such as '2011-12-03' ",
object : Coercing<LocalDate, String> {
//override few functions here
}
)

val graphqlZonedDateTimeType = GraphQLScalarType("ZonedDateTime",
" ISO date-time format with an offset, such as '2011-12-03T10:15:30+01:00' ",
object : Coercing<ZonedDateTime, String> {
//override few functions here
}
)

最佳答案

这已在相关的github问题中得到了解答:
https://github.com/ExpediaDotCom/graphql-kotlin/issues/230

Example using Spring: https://github.com/ExpediaDotCom/graphql-kotlin/blob/master/example/src/main/kotlin/com/expedia/graphql/sample/query/SubQueries.kt

Since graphql-kotlin reflectively generates resolvers, you'll have to do something like the above example, or use KGraphQL or graphql-java directly

Another example to get the data from further up the query chain is to use the DataFetcherEnvironment. It was added here: #173

关于kotlin - 如何在带有ktor框架的graphql-kotlin中进行字段级解析器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56397973/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com