Skip to content
This repository was archived by the owner on May 16, 2019. It is now read-only.

Add scalar deserializers to the objectMapper #46

Merged
merged 2 commits into from
Jan 8, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ abstract class ScalarDSL<T : Any, Raw : Any>(kClass: KClass<T>, block: ScalarDSL

var coercion: ScalarCoercion<T, Raw>? = null

internal fun createCoercion() : ScalarCoercion<T, Raw> {
fun createCoercion() : ScalarCoercion<T, Raw> {
return coercion ?: createCoercionFromFunctions()
}

abstract protected fun createCoercionFromFunctions() : ScalarCoercion<T, Raw>
protected abstract fun createCoercionFromFunctions() : ScalarCoercion<T, Raw>
}
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -44,6 +48,7 @@ class SchemaBuilder<Context : Any>(private val init: SchemaBuilder<Context>.() -

fun <T : Any>stringScalar(kClass: KClass<T>, block: ScalarDSL<T, String>.() -> Unit){
val scalar = StringScalarDSL(kClass, block)
configuration.appendMapper(scalar, kClass)
model.addScalar(TypeDef.Scalar(scalar.name, kClass, scalar.createCoercion(), scalar.description))
}

Expand All @@ -53,6 +58,7 @@ class SchemaBuilder<Context : Any>(private val init: SchemaBuilder<Context>.() -

fun <T : Any>intScalar(kClass: KClass<T>, block: ScalarDSL<T, Int>.() -> Unit){
val scalar = IntScalarDSL(kClass, block)
configuration.appendMapper(scalar, kClass)
model.addScalar(TypeDef.Scalar(scalar.name, kClass, scalar.createCoercion(), scalar.description))
}

Expand All @@ -62,6 +68,7 @@ class SchemaBuilder<Context : Any>(private val init: SchemaBuilder<Context>.() -

fun <T : Any>floatScalar(kClass: KClass<T>, block: ScalarDSL<T, Double>.() -> Unit){
val scalar = DoubleScalarDSL(kClass, block)
configuration.appendMapper(scalar, kClass)
model.addScalar(TypeDef.Scalar(scalar.name, kClass, scalar.createCoercion(), scalar.description))
}

Expand All @@ -71,6 +78,7 @@ class SchemaBuilder<Context : Any>(private val init: SchemaBuilder<Context>.() -

fun <T : Any>longScalar(kClass: KClass<T>, block: ScalarDSL<T, Long>.() -> Unit){
val scalar = LongScalarDSL(kClass, block)
configuration.appendMapper(scalar, kClass)
model.addScalar(TypeDef.Scalar(scalar.name, kClass, scalar.createCoercion(), scalar.description))
}

Expand All @@ -80,6 +88,7 @@ class SchemaBuilder<Context : Any>(private val init: SchemaBuilder<Context>.() -

fun <T : Any>booleanScalar(kClass: KClass<T>, block: ScalarDSL<T, Boolean>.() -> Unit){
val scalar = BooleanScalarDSL(kClass, block)
configuration.appendMapper(scalar, kClass)
model.addScalar(TypeDef.Scalar(scalar.name, kClass, scalar.createCoercion(), scalar.description))
}

Expand Down Expand Up @@ -160,4 +169,18 @@ class SchemaBuilder<Context : Any>(private val init: SchemaBuilder<Context>.() -
inline fun <reified T : Any> inputType() {
inputType(T::class, {})
}
}

inline fun <T: Any, reified Raw: Any> SchemaConfigurationDSL.appendMapper(scalar: ScalarDSL<T, Raw>, kClass: KClass<T>) {
objectMapper.registerModule(SimpleModule().addDeserializer(kClass.java, object : UsesDeserializer<T>() {
override fun deserialize(p: JsonParser, ctxt: DeserializationContext?): T? {
return scalar
.createCoercion()
.deserialize(p.readValueAs(Raw::class.java))
}
}))
}

open class UsesDeserializer<T>(vc: Class<*>? = null) : StdDeserializer<T>(vc) {
override fun deserialize(p: JsonParser, ctxt: DeserializationContext?): T? = TODO("Implement")
}
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,12 @@ class ScalarsSpecificationTest {
assertThat(response.extract<Boolean>("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`(){
Expand All @@ -167,4 +172,76 @@ class ScalarsSpecificationTest {
val response = deserialize(schema.execute("{double(double: $value)}"))
assertThat(response.extract<Double>("data/double"), equalTo(value))
}

@Test
fun `Scalars within input variables`(){
val schema = KGraphQL.schema {
booleanScalar<Boo> {
deserialize = ::Boo
serialize = { (boolean) -> boolean }
}
longScalar<Lon> {
deserialize = ::Lon
serialize = { (long) -> long }
}
floatScalar<Dob> {
deserialize = ::Dob
serialize = { (double) -> double }
}
intScalar<Num> {
deserialize = ::Num
serialize = { (num) -> num }
}
stringScalar<Str> {
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<Boolean>("data/boo"), equalTo(booValue))
assertThat(response.extract<Int>("data/lon"), equalTo(lonValue.toInt()))
assertThat(response.extract<Double>("data/dob"), equalTo(dobValue))
assertThat(response.extract<Int>("data/num"), equalTo(numValue))
assertThat(response.extract<String>("data/str"), equalTo(strValue))

assertThat(response.extract<Boolean>("data/multi/boo"), equalTo(false))
assertThat(response.extract<String>("data/multi/str"), equalTo("String"))
assertThat(response.extract<Int>("data/multi/num"), equalTo(25))
}
}