diff --git a/gradle.properties b/gradle.properties index 3c3aa51..d9c01c5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,7 +4,7 @@ kotlin.code.style=official specifyKotlinAsDependency=false projectGroup=ru.dbotthepony.kommons -projectVersion=1.6.0 +projectVersion=1.7.0 guavaDepVersion=33.0.0 gsonDepVersion=2.8.9 diff --git a/gson/src/main/kotlin/ru/dbotthepony/kommons/gson/KOptionalTypeAdapter.kt b/gson/src/main/kotlin/ru/dbotthepony/kommons/gson/KOptionalTypeAdapter.kt new file mode 100644 index 0000000..6340290 --- /dev/null +++ b/gson/src/main/kotlin/ru/dbotthepony/kommons/gson/KOptionalTypeAdapter.kt @@ -0,0 +1,53 @@ +package ru.dbotthepony.kommons.gson + +import com.google.gson.Gson +import com.google.gson.JsonSyntaxException +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 ru.dbotthepony.kommons.core.KOptional +import java.lang.reflect.ParameterizedType + +@Suppress("DEPRECATION") +object KOptionalTypeAdapter : TypeAdapterFactory { + override fun create(gson: Gson, type: TypeToken): TypeAdapter? { + if (type.rawType === KOptional.Nullable::class.java || type.rawType === KOptional::class.java || type.rawType === KOptional.NotNull::class.java) { + val notnull = type.rawType === KOptional.NotNull::class.java + val param = (type.type as? ParameterizedType ?: return null).actualTypeArguments[0] + val token = TypeToken.get(param) + val isBool = token.rawType === Boolean::class.java + + return object : TypeAdapter>() { + private val adapter0 = gson.getAdapter(token) as TypeAdapter + + override fun write(out: JsonWriter, value: KOptional?) { + if (value === null) { + out.nullValue() + } else if (value.isPresent) { + adapter0.write(out, value.value) + } + } + + override fun read(`in`: JsonReader): KOptional { + if (isBool) { + if (notnull) { + return KOptional((adapter0.read(`in`) ?: throw JsonSyntaxException("This KOptional does not accept nulls")) as Boolean) as KOptional + } else { + return KOptional(adapter0.read(`in`) as Boolean?) as KOptional + } + } else { + if (notnull) { + return KOptional(adapter0.read(`in`) ?: throw JsonSyntaxException("This KOptional does not accept nulls")) + } else { + return KOptional(adapter0.read(`in`)) + } + } + } + } as TypeAdapter + } else { + return null + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/kommons/core/KOptional.kt b/src/main/kotlin/ru/dbotthepony/kommons/core/KOptional.kt index 953d441..e624cdc 100644 --- a/src/main/kotlin/ru/dbotthepony/kommons/core/KOptional.kt +++ b/src/main/kotlin/ru/dbotthepony/kommons/core/KOptional.kt @@ -95,10 +95,10 @@ class KOptional private constructor(private val _value: T, val isPresent: Boo } // gson hack since type token can't diff between nullable and non-null types - @Deprecated("internal class") - internal class Nullable private constructor() - @Deprecated("internal class") - internal class NotNull private constructor() + @Deprecated("reflection class, don't use directly") + class Nullable private constructor() + @Deprecated("reflection class, don't use directly") + class NotNull private constructor() companion object { private val EMPTY = KOptional(null, false)