Skip to content

Instantly share code, notes, and snippets.

@Aracem
Last active November 30, 2018 10:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Aracem/c7187d850bd3bfe034793e714d74b300 to your computer and use it in GitHub Desktop.
Save Aracem/c7187d850bd3bfe034793e714d74b300 to your computer and use it in GitHub Desktop.
Gson adapter to add kotlin optionals check to gson deserializer
private val TAG: String = "GsonKotlinAdapter"
/**
* GsonKotlinAdapterFactory inspired by https://github.com/sargunv/gson-kotlin
*/
internal class GsonKotlinAdapterFactory : TypeAdapterFactory {
private val Class<*>.isKotlinClass: Boolean
get() = declaredAnnotations.find { it.annotationClass.java.name == "kotlin.Metadata" } != null
override fun <T : Any> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? {
if (!type.rawType.isKotlinClass)
return null
val kClass = (type.rawType as Class<*>).kotlin
@Suppress("UNCHECKED_CAST")
return Adapter(this, gson, type, kClass as KClass<T>)
}
class Adapter<T : Any>(
factory: GsonKotlinAdapterFactory,
gson: Gson,
type: TypeToken<T>,
private val kClass: KClass<T>
) : TypeAdapter<T>() {
val delegate: TypeAdapter<T> = gson.getDelegateAdapter(factory, type)
override fun write(out: JsonWriter, value: T) = delegate.write(out, value)
override fun read(input: JsonReader): T = delegate.read(input).apply { doNullCheck(this) }
private fun doNullCheck(value: T?) {
kClass.declaredMemberProperties.forEach { prop ->
prop.isAccessible = true
if (!prop.returnType.isMarkedNullable && value?.let { prop(it) } == null) {
val messageError = "Field: '${prop.name}' in Class '${kClass.simpleName}' is" +
" not marked nullable but found null value"
Log.e(TAG, messageError)
throw JsonParseException(messageError)
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment