All Downloads are FREE. Search and download functionalities are using the official Maven repository.

money.rave.common.backend.gson.GsonKotlinAdapterFactory.kt Maven / Gradle / Ivy

package money.rave.common.backend.gson

import com.google.gson.Gson
import com.google.gson.JsonParseException
import com.google.gson.TypeAdapter
import com.google.gson.TypeAdapterFactory
import com.google.gson.reflect.TypeToken
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonWriter
import kotlin.reflect.KClass
import kotlin.reflect.full.declaredMemberProperties
import kotlin.reflect.jvm.isAccessible

class GsonKotlinAdapterFactory(
    private val checkNulls: Boolean = true
) : TypeAdapterFactory {

    private val Class<*>.isKotlinClass: Boolean
        get() = declaredAnnotations.find { it.annotationClass.java.name == "kotlin.Metadata" } != null

    override fun  create(gson: Gson, type: TypeToken): TypeAdapter? {
        if (!type.rawType.isKotlinClass)
            return null

        val kClass = (type.rawType as Class<*>).kotlin

        @Suppress("UNCHECKED_CAST")
        return Adapter(this, gson, type, kClass as KClass, checkNulls)
    }

    class Adapter(
            factory: GsonKotlinAdapterFactory,
            gson: Gson,
            type: TypeToken,
            private val kClass: KClass,
            private val checkNulls: Boolean
    ) : TypeAdapter() {

        val delegate: TypeAdapter = gson.getDelegateAdapter(factory, type)

        override fun write(out: JsonWriter, value: T) {
            delegate.write(out, value)
        }

        override fun read(input: JsonReader): T {
            return delegate.read(input).apply {
                if (checkNulls) doNullCheck(this)
            }
        }

        private fun doNullCheck(value: T) {
            kClass.declaredMemberProperties.forEach { prop ->
                prop.isAccessible = true
                if (!prop.returnType.isMarkedNullable && prop(value) == null)
                    throw JsonParseException(
                            "Field: '${prop.name}' in Class '${prop.returnType.javaClass.typeName}' is not marked nullable but found null value"
                    )
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy