From 0976631bcd7ee29e45d1cdbd7a6875cbe4359117 Mon Sep 17 00:00:00 2001 From: Andrzej Zabost <5508894+azabost@users.noreply.github.com> Date: Thu, 29 Jun 2023 02:13:59 +0200 Subject: [PATCH] WIP: Try supporting arrays by using ArrayTypeAdapter --- .../codified/gson/CodifiedEnumTypeAdapter.kt | 34 +++++++++++++++++-- .../codified/gson/GsonTest.kt | 14 ++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/enums-gson/src/main/kotlin/pl/brightinventions/codified/gson/CodifiedEnumTypeAdapter.kt b/enums-gson/src/main/kotlin/pl/brightinventions/codified/gson/CodifiedEnumTypeAdapter.kt index b74ec03..cf9e286 100644 --- a/enums-gson/src/main/kotlin/pl/brightinventions/codified/gson/CodifiedEnumTypeAdapter.kt +++ b/enums-gson/src/main/kotlin/pl/brightinventions/codified/gson/CodifiedEnumTypeAdapter.kt @@ -3,12 +3,15 @@ package pl.brightinventions.codified.gson import com.google.gson.Gson import com.google.gson.TypeAdapter import com.google.gson.TypeAdapterFactory +import com.google.gson.internal.`$Gson$Types` +import com.google.gson.internal.bind.ArrayTypeAdapter import com.google.gson.reflect.TypeToken import com.google.gson.stream.JsonReader import com.google.gson.stream.JsonWriter import pl.brightinventions.codified.Codified import pl.brightinventions.codified.enums.CodifiedEnum import pl.brightinventions.codified.enums.CodifiedEnumDecoder +import java.lang.reflect.GenericArrayType import java.lang.reflect.ParameterizedType class CodifiedEnumTypeAdapter( @@ -21,16 +24,43 @@ class CodifiedEnumTypeAdapter( class Factory : TypeAdapterFactory { override fun create(gson: Gson, typeToken: TypeToken?): TypeAdapter? { - if (typeToken?.rawType != CodifiedEnum::class.java) { + if (typeToken == null) { return null } + if (typeToken.rawType == CodifiedEnum::class.java) { + return createCodifiedEnumTypeAdapter(typeToken, gson) + } + + val type = typeToken.type + if (!(type is GenericArrayType || type is Class<*> && type.isArray)) { + return null + } + + val componentType = `$Gson$Types`.getArrayComponentType(type) + + //if (componentRawType == CodifiedEnum::class.java) ? + //val adapter: TypeAdapter<*> = createCodifiedEnumTypeAdapter(TypeToken.get(componentType), gson)// as TypeAdapter + + @Suppress("UNCHECKED_CAST") + val arrayAdapter: TypeAdapter = ArrayTypeAdapter( + gson, + gson.getAdapter(TypeToken.get(componentType)), + `$Gson$Types`.getRawType(componentType) // TODO won't compile + ) as TypeAdapter + + return arrayAdapter + } + + private fun createCodifiedEnumTypeAdapter( + typeToken: TypeToken, + gson: Gson + ): TypeAdapter { val parameterizedType = typeToken.type as ParameterizedType val enumType = parameterizedType.actualTypeArguments[0] val enumTypeToken = TypeToken.get(enumType) val codeType = parameterizedType.actualTypeArguments[1] val codeAdapter = gson.getAdapter(TypeToken.get(codeType)) - @Suppress("UNCHECKED_CAST") return CodifiedEnumTypeAdapter(enumTypeToken, codeAdapter) as TypeAdapter } diff --git a/enums-gson/src/test/kotlin/pl/brightinventions/codified/gson/GsonTest.kt b/enums-gson/src/test/kotlin/pl/brightinventions/codified/gson/GsonTest.kt index 5507cb4..ed0e751 100644 --- a/enums-gson/src/test/kotlin/pl/brightinventions/codified/gson/GsonTest.kt +++ b/enums-gson/src/test/kotlin/pl/brightinventions/codified/gson/GsonTest.kt @@ -52,6 +52,20 @@ class GsonTest { wrapper.intEnum.code().shouldEqual(123) } + @Test + fun `known and unknown enums should be serialized`() { + val enums = listOf>( + CodifiedEnum.Known(StringEnum.BAR), + CodifiedEnum.Unknown("hello"), + CodifiedEnum.Known(StringEnum.FOO), + CodifiedEnum.Unknown("world"), + ) + + val string = gson.toJson(enums) + + string.shouldEqual("") + } + @Test fun `known and unknown enums in a wrapper should be serialized`() { val enums = listOf>(