https://kotlinlang.org logo
#serialization
Title
# serialization
c

Colton Idle

09/28/2023, 4:45 PM
I have
Copy code
@Serializable
data class Outer(
val innerName: Inner
)
and then I have an instance of this Outer class. How can I do something like this
outer.innerName.getSerializedName()
Basically. I need to save the name of the field onto disk. I can do
outer.innerName::class.java.simpleName
but that gives me "Inner" instead of what I want which is "innerName".
c

Casey Brooks

09/28/2023, 5:18 PM
innerName
is a property of the
Outer
class, not
Inner
. So you need to use reflection on
Outer::class
instead.
outer.innerName
is a reference to an instance of
Inner
, so
outer.innerName::class.java.simpleName
gives you the class name for
Inner
. For example:
Copy code
Outer::class.java.declaredFields.map { it.name } // [innerName]
Note that this gives you the Java field name for that property, not necessarily the serial name. If you’re not using any obfuscation or
@SerialName
annotations, they should be the same, but it’s not really guaranteed. If you do need the actual serial name, you’ll probably need to write a custom format for persisting that data to disk (which also has the benefit of working on other targets besides JVM)
e

ephemient

09/28/2023, 5:32 PM
Copy code
Outer.serializer().descriptor.getElementName(0)
c

Colton Idle

09/28/2023, 6:00 PM
Using descriptor means I'm using "reflection", right?
e

ephemient

09/28/2023, 6:01 PM
it's not reflection, serialization descriptors are generated at compile time
c

Colton Idle

09/28/2023, 6:11 PM
gotcha. okay. GetElementName(0) made me think that its reflection based or something. Wonder if there's anyway to do it without needing the magic number of 0.
this example is slimmed down from my actual example where I have
Copy code
@Serializable
data class Outer(
val innerName: Inner
val fooName: Foo
val barName: Bar
)
and I'm just trying to write a function to get the left side of the
:
e

ephemient

09/28/2023, 6:14 PM
Copy code
for (i in 0 until descriptor.getElementCount) {
    if (descriptor.getElementDescriptor(i) == Inner.serializer().descriptor)
        return descriptor.getElementName(i)
but it doesn't provide a mapping between serial name and property name, if that's what you're looking for
any reason why?
c

Casey Brooks

09/28/2023, 6:22 PM
Reflection is specifically the ability of a program to introspect itself at runtime (especially with the ability to change itself at runtime). It’s a form of metaprogramming, which is a program that understands its own structure. Kotlinx.serialization is a form of metaprogramming, but since it does that by generating code at compile time, it’s not reflection.
e

ephemient

09/28/2023, 6:25 PM
yeah the line is a little fuzzy, but in general on the JVM "reflection" refers to what is provided by the platform (plus what is built on top of it, such as kotlin.reflect), while kotlinx.serialization doesn't require any runtime support (except for extensions like
fun <T> KClass<T>.serializer()
)
going a bit off topic… the line can be a little fuzzy when it comes to things like https://doc.qt.io/qt-5/metaobjects.html where it's the "reflection" "runtime" that Qt uses isn't part of C++ itself but comes from Qt. but it's pretty well-defined in Java