yshrsmz / kgql

GraphQL Document wrapper generator for Kotlin Multiplatform Project and Android
Apache License 2.0
57 stars 2 forks source link

handle default value of operation #7

Open yshrsmz opened 5 years ago

yshrsmz commented 5 years ago

https://github.com/Kotlin/kotlinx.serialization/pull/276

JsonObject could be the key. Instead of generating Variables class

yshrsmz commented 5 years ago

tested with iosX64

enum class Type {
    FOO, BAR
}

@Serializable
data class Name(val value: String)

@Serializable
data class User(val id: String, val age: Int, val name: Name, val type: Type)

fun test() {
    val json = json {
        "key" to "string"
        "key2" to 0
        "user" to Json.plain.toJson(User.serializer(), User("idstring", 32, Name("namestring"), Type.BAR))
    }

    val stringified = Json.stringify(JsonObjectSerializer, json)
    println("map: $stringified")
    // map: {"key":"string","key2":0,"user":{"id":"idstring","age":32,"name":{"value":"namestring"},"type":"BAR"}}
}

root element can be JsonObject. This way we can ignore value for arguments not provided

yshrsmz commented 5 years ago

draft

sealed class KgqlValue<out T : Any?> {
    data class Some<out T : Any?>(val value: T) : KgqlValue<T>()
    object None : KgqlValue<Nothing>()
}

class Variables(val login: String) {
    private var name: KgqlValue<Int?> = KgqlValue.None
    private var id: KgqlValue<Int?> = KgqlValue.None
    private var company: KgqlValue<String?> = KgqlValue.None
    private var foo: KgqlValue<Float?> = KgqlValue.None
    private var logins: KgqlValue<List<String?>?> = KgqlValue.None

    fun name(name: Int?): Variables2 {
        this.name = KgqlValue.Some(name)
        return this
    }

    fun id(id: Int?): Variables2 {
        this.id = KgqlValue.Some(id)
        return this
    }

    fun company(company: String?): Variables2 {
        this.company = KgqlValue.Some(company)
        return this
    }

    fun foo(foo: Float?): Variables2 {
        this.foo = KgqlValue.Some(foo)
        return this
    }

    fun logins(logins: List<String?>?): Variables2 {
        this.logins = KgqlValue.Some(logins)
        return this
    }

    fun asJsonObject(): JsonObject {
        return json {
            "login" to login
            (name as? KgqlValue.Some)?.let { "name" to it.value }
            (id as? KgqlValue.Some)?.let { "id" to it.value }
            (company as? KgqlValue.Some)?.let { "company" to it.value }
            (foo as? KgqlValue.Some)?.let { "foo" to it.value }
            (logins as? KgqlValue.Some)?.let {
                "logins" to Json.plain.toJson(
                    NullableSerializer(NullableSerializer(String.serializer()).list),
                    it.value
                )
            }
        }
    }
}
yshrsmz commented 5 years ago

in order to serialize enum value properly, we need to know if a target value is enum or not. But to do this, we need schema. Without schema we can not distinguish enum from other custom type

we first need to resolve #1

yshrsmz commented 5 years ago

another workaround is to let users define serializer function for enums like below

enum class Type {
    FOO, BAR;

    companion object {
        fun serializer(): KSerializer<Type> = EnumSerializer(Type::class)
    }
}