Skip to content

Commit

Permalink
WIP: Try supporting arrays by using ArrayTypeAdapter
Browse files Browse the repository at this point in the history
  • Loading branch information
azabost committed Jun 29, 2023
1 parent 6f10657 commit 0976631
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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<T, C : Any>(
Expand All @@ -21,16 +24,43 @@ class CodifiedEnumTypeAdapter<T, C : Any>(

class Factory : TypeAdapterFactory {
override fun <T : Any> create(gson: Gson, typeToken: TypeToken<T>?): TypeAdapter<T>? {
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<T>

@Suppress("UNCHECKED_CAST")
val arrayAdapter: TypeAdapter<T> = ArrayTypeAdapter(
gson,
gson.getAdapter(TypeToken.get(componentType)),
`$Gson$Types`.getRawType(componentType) // TODO won't compile
) as TypeAdapter<T>

return arrayAdapter
}

private fun <T : Any> createCodifiedEnumTypeAdapter(
typeToken: TypeToken<T>,
gson: Gson
): TypeAdapter<T> {
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<T>
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,20 @@ class GsonTest {
wrapper.intEnum.code().shouldEqual(123)
}

@Test
fun `known and unknown enums should be serialized`() {
val enums = listOf<CodifiedEnum<StringEnum, String>>(
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<CodifiedEnum<StringEnum, String>>(
Expand Down

0 comments on commit 0976631

Please sign in to comment.