From 752b2353a52caa1fe78adcae8a27effa308d1aba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3gvan=20Olsen?= Date: Mon, 31 Dec 2018 17:08:57 +0000 Subject: [PATCH] #43: Added scalar deserializers to the objectMapper --- .../kgraphql/schema/dsl/ScalarDSL.kt | 4 +- .../kgraphql/schema/dsl/SchemaBuilder.kt | 23 ++++++ .../typesystem/ScalarsSpecificationTest.kt | 79 ++++++++++++++++++- 3 files changed, 103 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/com/github/pgutkowski/kgraphql/schema/dsl/ScalarDSL.kt b/src/main/kotlin/com/github/pgutkowski/kgraphql/schema/dsl/ScalarDSL.kt index 2ef945fa..3c3c86e7 100644 --- a/src/main/kotlin/com/github/pgutkowski/kgraphql/schema/dsl/ScalarDSL.kt +++ b/src/main/kotlin/com/github/pgutkowski/kgraphql/schema/dsl/ScalarDSL.kt @@ -24,9 +24,9 @@ abstract class ScalarDSL(kClass: KClass, block: ScalarDSL var coercion: ScalarCoercion? = null - internal fun createCoercion() : ScalarCoercion { + fun createCoercion() : ScalarCoercion { return coercion ?: createCoercionFromFunctions() } - abstract protected fun createCoercionFromFunctions() : ScalarCoercion + protected abstract fun createCoercionFromFunctions() : ScalarCoercion } \ No newline at end of file diff --git a/src/main/kotlin/com/github/pgutkowski/kgraphql/schema/dsl/SchemaBuilder.kt b/src/main/kotlin/com/github/pgutkowski/kgraphql/schema/dsl/SchemaBuilder.kt index bb58c4ed..bf82d2cd 100644 --- a/src/main/kotlin/com/github/pgutkowski/kgraphql/schema/dsl/SchemaBuilder.kt +++ b/src/main/kotlin/com/github/pgutkowski/kgraphql/schema/dsl/SchemaBuilder.kt @@ -1,5 +1,9 @@ package com.github.pgutkowski.kgraphql.schema.dsl +import com.fasterxml.jackson.core.JsonParser +import com.fasterxml.jackson.databind.DeserializationContext +import com.fasterxml.jackson.databind.deser.std.StdDeserializer +import com.fasterxml.jackson.databind.module.SimpleModule import com.github.pgutkowski.kgraphql.schema.Schema import com.github.pgutkowski.kgraphql.schema.SchemaException import com.github.pgutkowski.kgraphql.schema.model.EnumValueDef @@ -44,6 +48,7 @@ class SchemaBuilder(private val init: SchemaBuilder.() - fun stringScalar(kClass: KClass, block: ScalarDSL.() -> Unit){ val scalar = StringScalarDSL(kClass, block) + configuration.appendMapper(scalar, kClass) model.addScalar(TypeDef.Scalar(scalar.name, kClass, scalar.createCoercion(), scalar.description)) } @@ -53,6 +58,7 @@ class SchemaBuilder(private val init: SchemaBuilder.() - fun intScalar(kClass: KClass, block: ScalarDSL.() -> Unit){ val scalar = IntScalarDSL(kClass, block) + configuration.appendMapper(scalar, kClass) model.addScalar(TypeDef.Scalar(scalar.name, kClass, scalar.createCoercion(), scalar.description)) } @@ -62,6 +68,7 @@ class SchemaBuilder(private val init: SchemaBuilder.() - fun floatScalar(kClass: KClass, block: ScalarDSL.() -> Unit){ val scalar = DoubleScalarDSL(kClass, block) + configuration.appendMapper(scalar, kClass) model.addScalar(TypeDef.Scalar(scalar.name, kClass, scalar.createCoercion(), scalar.description)) } @@ -71,6 +78,7 @@ class SchemaBuilder(private val init: SchemaBuilder.() - fun longScalar(kClass: KClass, block: ScalarDSL.() -> Unit){ val scalar = LongScalarDSL(kClass, block) + configuration.appendMapper(scalar, kClass) model.addScalar(TypeDef.Scalar(scalar.name, kClass, scalar.createCoercion(), scalar.description)) } @@ -80,6 +88,7 @@ class SchemaBuilder(private val init: SchemaBuilder.() - fun booleanScalar(kClass: KClass, block: ScalarDSL.() -> Unit){ val scalar = BooleanScalarDSL(kClass, block) + configuration.appendMapper(scalar, kClass) model.addScalar(TypeDef.Scalar(scalar.name, kClass, scalar.createCoercion(), scalar.description)) } @@ -160,4 +169,18 @@ class SchemaBuilder(private val init: SchemaBuilder.() - inline fun inputType() { inputType(T::class, {}) } +} + +inline fun SchemaConfigurationDSL.appendMapper(scalar: ScalarDSL, kClass: KClass) { + objectMapper.registerModule(SimpleModule().addDeserializer(kClass.java, object : UsesDeserializer() { + override fun deserialize(p: JsonParser, ctxt: DeserializationContext?): T? { + return scalar + .createCoercion() + .deserialize(p.readValueAs(Raw::class.java)) + } + })) +} + +open class UsesDeserializer(vc: Class<*>? = null) : StdDeserializer(vc) { + override fun deserialize(p: JsonParser, ctxt: DeserializationContext?): T? = TODO("Implement") } \ No newline at end of file diff --git a/src/test/kotlin/com/github/pgutkowski/kgraphql/specification/typesystem/ScalarsSpecificationTest.kt b/src/test/kotlin/com/github/pgutkowski/kgraphql/specification/typesystem/ScalarsSpecificationTest.kt index 78a78146..accc86de 100644 --- a/src/test/kotlin/com/github/pgutkowski/kgraphql/specification/typesystem/ScalarsSpecificationTest.kt +++ b/src/test/kotlin/com/github/pgutkowski/kgraphql/specification/typesystem/ScalarsSpecificationTest.kt @@ -147,7 +147,12 @@ class ScalarsSpecificationTest { assertThat(response.extract("data/boolean"), equalTo(value)) } - data class Dob(val double : Double) + data class Boo(val boolean: Boolean) + data class Lon(val long: Long) + data class Dob(val double: Double) + data class Num(val int: Int) + data class Str(val string: String) + data class Multi(val boo: Boo, val str: String, val num: Num) @Test fun `Schema may declare custom double scalar type`(){ @@ -167,4 +172,76 @@ class ScalarsSpecificationTest { val response = deserialize(schema.execute("{double(double: $value)}")) assertThat(response.extract("data/double"), equalTo(value)) } + + @Test + fun `Scalars within input variables`(){ + val schema = KGraphQL.schema { + booleanScalar { + deserialize = ::Boo + serialize = { (boolean) -> boolean } + } + longScalar { + deserialize = ::Lon + serialize = { (long) -> long } + } + floatScalar { + deserialize = ::Dob + serialize = { (double) -> double } + } + intScalar { + deserialize = ::Num + serialize = { (num) -> num } + } + stringScalar { + deserialize = ::Str + serialize = { (str) -> str } + } + + query("boo") { resolver { boo : Boo -> boo } } + query("lon") { resolver { lon : Lon -> lon } } + query("dob") { resolver { dob : Dob -> dob } } + query("num") { resolver { num : Num -> num } } + query("str") { resolver { str : Str -> str } } + query("multi") { resolver { -> Multi(Boo(false), "String", Num(25)) } } + } + + val booValue = true + val lonValue = 124L + val dobValue = 2.5 + val numValue = 155 + val strValue = "Test" + val d = '$' + + val req = """ + query Query(${d}boo: Boo!, ${d}lon: Lon!, ${d}dob: Dob!, ${d}num: Num!, ${d}str: Str!){ + boo(boo: ${d}boo) + lon(lon: ${d}lon) + dob(dob: ${d}dob) + num(num: ${d}num) + str(str: ${d}str) + multi { boo, str, num } + } + """.trimIndent() + + val values = """ + { + "boo": $booValue, + "lon": $lonValue, + "dob": $dobValue, + "num": $numValue, + "str": "$strValue" + } + """.trimIndent() + + val response = deserialize(schema.execute(req, values)) + assertThat(response.extract("data/boo"), equalTo(booValue)) + assertThat(response.extract("data/lon"), equalTo(lonValue.toInt())) + assertThat(response.extract("data/dob"), equalTo(dobValue)) + assertThat(response.extract("data/num"), equalTo(numValue)) + assertThat(response.extract("data/str"), equalTo(strValue)) + + assertThat(response.extract("data/multi/boo"), equalTo(false)) + assertThat(response.extract("data/multi/str"), equalTo("String")) + assertThat(response.extract("data/multi/num"), equalTo(25)) + } } \ No newline at end of file