Is it possible to deserialize an array into an obj...
# serialization
m
Is it possible to deserialize an array into an object? For example, turning something like
["Bob", 24]
into
class Person(val name: String, val age: Int)
. Assuming of course that I already know the array corresponds to the
Person
class (in reality, my data looks more like
{ "person": ["Bob", 24] }
j
There's an issue for automatically doing this, but otherwise yes that's a simple custom serializer where you read the array values and then invoke the constructor with the values
m
Is there a way to do it more generically? I have like 50 different types of these classes
j
Hmmm you may be able to write a generalized serializer which does this, but I haven't tried.
I know how to do it with Moshi, but not kotlinx.seriazliation. But rarely can you do something with one and not the other.
m
Ahh I haven't heard of that library before. Well I'm not particular tied to kotlinx, I'll try that if I can't get it to work
Wow you were right, I was able to come up with an extremely elegant solution. All I have to do is configure the sealed class with a one-line serializer implementation. Here's the final solution, in case anyone finds this in the future: https://gist.github.com/mattco98/99a6778609e21a95d68c7dbfd949cc9f
👍 1
e
doing your own reflection bypasses a lot of kotlinx.serialization (and doesn't work on non-JVM platforms). why not work with kotlinx.serialization?
m
Because I didn't know how, that's kind of why I was here asking questions after all 😛 But that solution requires constructing and passing the serializer explicitly to the decode/encode function. Is there a way to use this solution when I have a huge tree of nested types?
Ideally I would just say
Serializable(with = ...)
, but that (obviously) overwrites the compiler-generated serializer
Actually you could use the SerializersModule
polymorphic
I assume. If that works, then this solution is definitely much better. Thanks for improving my hack 🙂
e
that will require manually registering them - you don't get the automatic registration that
@Serializable
does. but yes, it would work
👍 1
you could use
Copy code
polymorphic(EnumVariant::class) {
    for (klass in EnumVariant::class.sealedSubclasses) subclass(klass)
}
if you're on JVM and include
kotlin-reflect
but otherwise that lookup is something that currently can't be done at runtime on other platforms
m
I tried doing that, but it gives me
Cannot use 'CapturedType(out UncheckedType)' as reified type parameter
(I do have the
kotlin-reflect
dependency)
e
hmm, that's interesting. can be worked around with
Copy code
@OptIn(InternalSerializationApi::class)
subclass(klass as KClass<EnumVariant>, klass.serializer())
but I don't think it's meant to be used that way
m
Good enough for me, at least for now
e
it's not as well documented, but you could also implement an alternative format which works like JSON except for polymorphism. then the default generated serializers will just work
the downside is that it misses some standard Json features (e.g.
ignoreUnknownKeys
,
useAlternativeNames
, etc.) which are definitely possible to re-implement but would take more effort
m
Oh very interesting, I hadn't considered that approach. The lack of features is fine, I don't think I need any of them in this particular instance. This solution I think is the most appealing for me, thanks once again 🙂