https://kotlinlang.org logo
Title
r

Raymond Gao

04/18/2020, 5:44 PM
Hi I'm playing around with some serialization using reflection. I would like to be able to serialize some simple classes into JSONObjects in the following way
val foo : Foo = Foo()
var jobj : JSONObject = serialize(foo)
var foo2 : Foo = construct(jobj, Foo::class)
The methods serialize and construct will inspect the object using reflection, find any fields that match a set of constraints and add their values to a json object or send them into the appropriate constructor of
Foo
to create a new object It works until I run into Generics
class Foo(val map : Map<String, Int>)
{
...
}
I'm having some difficulty getting the type parameters passed into
Map
at runtime. My friend has told me about the concept of type erasure. It seems that kotlin throws away these arguments at runtime. I have resorted to annotating the field with the appropriate types for now, but it causes some ugly duplication of information already typed down.
class Foo(@param:GenericsHint([String::class, Int::class]) val map : Map<String, Int>)
Does anyone have any ideas on how I can get around this problem? Thanks 🙂
a

Adam Powell

04/18/2020, 6:15 PM
Yes, have a look at Moshi or kotlinx.serialization 🙂
r

Raymond Gao

04/18/2020, 6:15 PM
Will do, thanks.
j

Jakub Pi

04/18/2020, 8:23 PM
There are some advanced techniques for solving this problem revolving around passing a type token. I believe all the reflection-based JSON serialization frameworks use this technique. Gson uses TypeToken. Jackson has TypeReference. Ktor has an interesting solution around its httpclient get interface. kotlinx.serialization doesn't actually use reflection, it uses code generation to create descriptors. It will force you to write more boilerplate but you get the benefits of multiplatform, multiformat, and performance