Skip to content

Gradle GraphQL Scalar Mapping

dermakov edited this page Apr 29, 2023 · 4 revisions

To generate client DSL from our GraphQL schema, we have to provide mapping of scalars, defined in the schema, to Kotlin data types.

Default mapping

Kobby provides default mapping for some scalars:

GraphQL Scalar Kotlin Type
ID kotlin.Long
Int kotlin.Int
Long kotlin.Long
Float kotlin.Double
Double kotlin.Double
String kotlin.String
Boolean kotlin.Boolean

Custom mapping

You can configure your own mapping or override default mapping by means of kobby.kotlin.scalars property:

kobby {
    kotlin {
        scalars = mapOf(
            "ID" to typeOf("java.util", "UUID"),
            "Date" to typeOf("java.time", "LocalDate")
        )
    }
}

The scalars property is of type Map<String, KotlinType>, where key of the map is name of GraphQL scalar and value of the map is Kobby KotlinType:

package io.github.ermadmi78.kobby.generator.kotlin

class KotlinType(
    /** A fully-qualified package name. For example: kotlin.collections */
    val packageName: String,

    /** A fully-qualified class name. For example: Map.Entry */
    val className: String,

    val allowNull: Boolean = false,

    /** List of generics */
    val generics: List<KotlinType> = listOf()
) {
    fun nullable(): KotlinType =
        if (allowNull) this else KotlinType(packageName, className, true, generics)

    fun parameterize(vararg arguments: KotlinType): KotlinType =
        if (arguments.isEmpty()) this else KotlinType(packageName, className, allowNull, generics + arguments)

    fun nested(nestedClassName: String): KotlinType =
        KotlinType(packageName, "$className.$nestedClassName", allowNull, generics)
}

To simplify KotlinType creation, Kobby extension provides builder functions:

package io.github.ermadmi78.kobby

fun typeOf(packageName: String, className: String, vararg arguments: KotlinType) =
    KotlinType(packageName, className, false, arguments.toList())

fun typeOf(packageName: String, className: String, nullable: Boolean, vararg arguments: KotlinType) =
    KotlinType(packageName, className, nullable, arguments.toList())

For example, let configure Map<String, Any?> type for JSON scalar:

import io.github.ermadmi78.kobby.kobby

kobby {
    kotlin {
        scalars = mapOf(
            "JSON" to typeOf(
                "kotlin.collections", "Map",
                typeOf("kotlin", "String"),
                typeOf("kotlin", "Any", nullable = true)
            )
        )
    }
}

Let simplify our example by means of parameterize and nullable functions:

import io.github.ermadmi78.kobby.kobby

kobby {
    kotlin {
        scalars = mapOf(
            "JSON" to typeOf("kotlin.collections", "Map").parameterize(
                typeOf("kotlin", "String"),
                typeOf("kotlin", "Any").nullable()
            )
        )
    }
}

Kotlin standard type constants

The Kobby extension provides a set of predefined constants for standard Kotlin types. With the help of constants, we can rewrite our example like this:

import io.github.ermadmi78.kobby.kobby

kobby {
    kotlin {
        scalars = mapOf(
            "JSON" to typeMap.parameterize(typeString, typeAny.nullable())
        )
    }
}

All available constants:

Constant Kotlin Type
typeAny kotlin.Any
typeNumber kotlin.Number
typeByte kotlin.Byte
typeShort kotlin.Short
typeInt kotlin.Int
typeLong kotlin.Long
typeFloat kotlin.Float
typeDouble kotlin.Double
typeChar kotlin.Char
typeString kotlin.String
typeCharSequence kotlin.CharSequence
typeBoolean kotlin.Boolean
typeEnum kotlin.Enum
typeThrowable kotlin.Throwable
typeComparable kotlin.Comparable
typeIterable kotlin.collections.Iterable
typeCollection kotlin.collections.Collection
typeList kotlin.collections.List
typeSet kotlin.collections.Set
typeMap kotlin.collections.Map
typeMutableIterable kotlin.collections.MutableIterable
typeMutableCollection kotlin.collections.MutableCollection
typeMutableList kotlin.collections.MutableList
typeMutableSet kotlin.collections.MutableSet
typeMutableMap kotlin.collections.MutableMap
typeArray kotlin.Array
typeBooleanArray kotlin.BooleanArray
typeByteArray kotlin.ByteArray
typeCharArray kotlin.CharArray
typeShortArray kotlin.ShortArray
typeIntArray kotlin.IntArray
typeLongArray kotlin.LongArray
typeFloatArray kotlin.FloatArray
typeDoubleArray kotlin.DoubleArray

Custom Kotlinx Serializers

You can configure a custom serializer to any type associated with a scalar (see Kotlinx Serialization support):

kobby {
    kotlin {
        scalars = mapOf(
            "Date" to typeOf("java.time", "LocalDate")
                .serializer(
                    "io.github.ermadmi78.kobby.cinema.api.kobby.kotlin.dto", // package name
                    "LocalDateSerializer" // class name
                )
        )
    }
}