Skip to content

Instantly share code, notes, and snippets.

@samuel22gj
Last active December 17, 2021 08:34
Show Gist options
  • Save samuel22gj/dbbe1df999baed6de8fdf074ffcb11aa to your computer and use it in GitHub Desktop.
Save samuel22gj/dbbe1df999baed6de8fdf074ffcb11aa to your computer and use it in GitHub Desktop.
SafeBooleanTypeAdapter for Kotlin
class BooleanTypeAdapterTest {
@Test
fun testBooleanTypeAdapter() {
val gson = GsonBuilder()
.registerTypeAdapter(Boolean::class.javaObjectType, BooleanObjectTypeAdapter())
.registerTypeAdapter(Boolean::class.javaPrimitiveType, BooleanPrimitiveTypeAdapter())
.create()
assertEquals(null, gson.fromJson("""{"isBoolean"=null}""", Foo::class.java).isBoolean)
assertEquals(false, gson.fromJson("""{"isBoolean"=false}""", Foo::class.java).isBoolean)
assertEquals(true, gson.fromJson("""{"isBoolean"=true}""", Foo::class.java).isBoolean)
assertEquals(true, gson.fromJson("""{"isBoolean"="true"}""", Foo::class.java).isBoolean)
assertEquals(true, gson.fromJson("""{"isBoolean"="TrUe"}""", Foo::class.java).isBoolean)
assertEquals(false, gson.fromJson("""{"isBoolean"="false"}""", Foo::class.java).isBoolean)
assertEquals(false, gson.fromJson("""{"isBoolean"="FaLse"}""", Foo::class.java).isBoolean)
assertEquals(false, gson.fromJson("""{"isBoolean"=""}""", Foo::class.java).isBoolean)
assertEquals(false, gson.fromJson("""{"isBoolean"="0"}""", Foo::class.java).isBoolean)
assertEquals(true, gson.fromJson("""{"isBoolean"="1"}""", Foo::class.java).isBoolean)
assertEquals(false, gson.fromJson("""{"isBoolean"="2"}""", Foo::class.java).isBoolean)
assertEquals(false, gson.fromJson("""{"isBoolean"=0}""", Foo::class.java).isBoolean)
assertEquals(true, gson.fromJson("""{"isBoolean"=1}""", Foo::class.java).isBoolean)
assertEquals(false, gson.fromJson("""{"isBoolean"=2}""", Foo::class.java).isBoolean)
assertEquals(false, gson.fromJson("""{"isBoolean"=[1,2]}""", Foo::class.java).isBoolean)
assertEquals(false, gson.fromJson("""{"isBoolean"={}}""", Foo::class.java).isBoolean)
assertEquals(false, gson.fromJson("""{"isBoolean"={"a"="b"}}""", Foo::class.java).isBoolean)
assertEquals(false, gson.fromJson("""{"isBoolean"=null}""", Bar::class.java).isBoolean)
assertEquals(false, gson.fromJson("""{"isBoolean"=false}""", Bar::class.java).isBoolean)
assertEquals(true, gson.fromJson("""{"isBoolean"=true}""", Bar::class.java).isBoolean)
assertEquals(true, gson.fromJson("""{"isBoolean"="true"}""", Bar::class.java).isBoolean)
assertEquals(true, gson.fromJson("""{"isBoolean"="TrUe"}""", Bar::class.java).isBoolean)
assertEquals(false, gson.fromJson("""{"isBoolean"="false"}""", Bar::class.java).isBoolean)
assertEquals(false, gson.fromJson("""{"isBoolean"="FaLse"}""", Bar::class.java).isBoolean)
assertEquals(false, gson.fromJson("""{"isBoolean"=""}""", Bar::class.java).isBoolean)
assertEquals(false, gson.fromJson("""{"isBoolean"="0"}""", Bar::class.java).isBoolean)
assertEquals(true, gson.fromJson("""{"isBoolean"="1"}""", Bar::class.java).isBoolean)
assertEquals(false, gson.fromJson("""{"isBoolean"="2"}""", Bar::class.java).isBoolean)
assertEquals(false, gson.fromJson("""{"isBoolean"=0}""", Bar::class.java).isBoolean)
assertEquals(true, gson.fromJson("""{"isBoolean"=1}""", Bar::class.java).isBoolean)
assertEquals(false, gson.fromJson("""{"isBoolean"=2}""", Bar::class.java).isBoolean)
assertEquals(false, gson.fromJson("""{"isBoolean"=[1,2]}""", Foo::class.java).isBoolean)
assertEquals(false, gson.fromJson("""{"isBoolean"={"a"="b"}}""", Foo::class.java).isBoolean)
}
data class Foo(var isBoolean: Boolean? = null)
data class Bar(var isBoolean: Boolean = false)
}
@Module
class GsonModule {
@Singleton
@Provides
fun provideGson(): Gson {
return GsonBuilder()
.registerTypeAdapter(Boolean::class.javaObjectType, BooleanObjectTypeAdapter())
.registerTypeAdapter(Boolean::class.javaPrimitiveType, BooleanPrimitiveTypeAdapter())
.create()
}
}
private val TRUE_STRINGS: Array<String> = arrayOf("true", "1")
class BooleanObjectTypeAdapter : JsonDeserializer<Boolean?>, JsonSerializer<Boolean?> {
override fun serialize(src: Boolean?, typeOfSrc: Type?, context: JsonSerializationContext?): JsonElement {
return if (src == null) {
JsonNull.INSTANCE
} else {
JsonPrimitive(src)
}
}
override fun deserialize(json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext?): Boolean? {
if (json == null || json.isJsonNull) {
return null
}
return when {
json !is JsonPrimitive -> false
json.isBoolean -> json.asBoolean
json.isNumber -> json.asNumber.toInt() == 1
json.isString -> TRUE_STRINGS.contains(json.asString.lowercase())
else -> false
}
}
}
class BooleanPrimitiveTypeAdapter : JsonDeserializer<Boolean>, JsonSerializer<Boolean> {
override fun serialize(src: Boolean?, typeOfSrc: Type?, context: JsonSerializationContext?): JsonElement {
return if (src == null) {
JsonPrimitive(false)
} else {
JsonPrimitive(src)
}
}
override fun deserialize(json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext?): Boolean {
if (json == null || json.isJsonNull) {
return false
}
return when {
json !is JsonPrimitive -> false
json.isBoolean -> json.asBoolean
json.isNumber -> json.asNumber.toInt() == 1
json.isString -> TRUE_STRINGS.contains(json.asString.lowercase())
else -> false
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment