I saw that 5.0.0 was released. Thanks for that. Th...
# graphql-kotlin
j
I saw that 5.0.0 was released. Thanks for that. The deprecation of Long and Double was something I had to work around a bit. We definitely need Long/Double numbers and not floats/ints. Using those is a bit of an antipattern in Kotlin unless you really know you don't need the precision. I would love some feedback on what the drawbacks are of this. I understand that javascript treats all numbers as 64 bit floats. Which raises the question why Doubles are not supported anymore since that is actually the closest thing Kotlin and Java have to what javascript supports natively. That translates as a 2^53 Long. So I understand why Longs were removed. We use Longs to send around timestamps in milliseconds after the epoch for that, Javascript's Doubles provide enough precision but Java's 32 bit Int doesn't. Json actually specify precision, which is why you can get frameworks like Jackson to deal with big ints and big decimals pretty easily. Beyond the limitations of javascript, are there any other concerns here? Not an issue for us because we actually use kotlin-js in the browser as well. So beyond bugs in kotlinx serialization (which we use for our multi platform graphql client), this won't affect us.
Copy code
@Component
class FormationGraphqlHooks : SchemaGeneratorHooks {
    override fun willGenerateGraphQLType(type: KType): GraphQLType? {
        return when (type.classifier as? KClass<*>) {
            Long::class -> longScalar
            Double::class -> doubleScalar
            else -> null
        }
    }
}

private val longScalar = GraphQLScalarType.newScalar().name("Long")
    .coercing(object : Coercing<Long,Any> {
    override fun serialize(dataFetcherResult: Any): Any {
        return dataFetcherResult
    }

    override fun parseValue(input: Any): Long {
        return input as Long
    }

    override fun parseLiteral(input: Any): Long {
        return input as Long
    }
}).build()

private val doubleScalar = GraphQLScalarType.newScalar().name("Double")
    .coercing(object : Coercing<Double,Any> {
        override fun serialize(dataFetcherResult: Any): Any {
            return dataFetcherResult
        }

        override fun parseValue(input: Any): Double {
            return input as Double
        }

        override fun parseLiteral(input: Any): Double {
            return input as Double
        }
    }).build()
Btw. might be nice to add this, or an improved example to your documentation since anyone doing anything remotely serious with numbers is going to be looking for a workable solution.
Maybe a better way to deal with this would be some kind of OptIn annotation if they have problematic scalars in their schema. So, warn the user about javascript issues with problematic built in types but allow them to opt in to those with an annotations.
r
GraphQL does specify
Float
as double-precision (https://spec.graphql.org/June2018/#sec-Float) and
Int
as 32-bit values. Therefore, it makes sense to treat Int as a Java Int, but not sure why
Float
is being treated as a Java
Float
instead of
Double
. Even the upstream graphql-java project correctly treats a GQL
Float
as a `Double`: https://github.com/graphql-java/graphql-java/blob/master/src/main/java/graphql/Scalars.java#L34.
s
Good call out, this is something we missed and should fix