2
\$\begingroup\$

I have a project that uses a library to save serialized objects in items and loads them again, when needed.
To do the de-/serialization, this library uses Gson.

Due to how Gson works and how the library is set up, I can't add support for custom types easily and thus have to rely heavily on reflection.
I don't like this, but it has to be like this, sadly.

I am asking, whether there is a way to make this code use more Kotlin idioms.
My issue is that because the fields I am accessing are private, the usual reflection using :: doesn't work.

Anyways, here is my code:

/**
 * Registers a custom GSON handler to handle the [Location] class.
 */
private fun registerGsonHandlers() {
    logger.entering(LobbyMain::class, "registerGsonHandlers")
    // Gets private static final Gson gson = new Gson();
    val fGson = NBTReflectionUtil::class.java.getDeclaredField("gson")
    fGson.isAccessible = true

    val modifiersField = Field::class.java.getDeclaredField("modifiers")
    modifiersField.isAccessible = true
    modifiersField.setInt(fGson, fGson.modifiers and Modifier.FINAL.inv())

    // Gets  private final List<TypeAdapterFactory> factories;
    val fFactories = Gson::class.java.getDeclaredField("factories")
    fFactories.isAccessible = true
    val factories = fFactories.get(fGson.get(null)) as List<*>

    // Sets private static final Gson gson
    fGson.set(null, GsonBuilder().apply {
        registerTypeAdapter(Location::class.java, LocationTypeAdapter)
        factories.forEach { this::registerTypeAdapterFactory }
    }.create())
    logger.exiting(LobbyMain::class, "registerGsonHandlers")
}

It pulls the Gson object out of the NBTReflectionUtil class, makes it modifiable and gets its list of TypeAdapterFactories.
I then create a new Gson object with all the old TypeAdapters and mine added and set it as the new Gson object for the library.

\$\endgroup\$
1
\$\begingroup\$

I'd group your code to make it more readable. Something like this:

fun getGson(): Field {
    val fGson = NBTReflectionUtil::class.java.getDeclaredField("gson")
    fGson.isAccessible = true
}

fun removeFinalModifier(field: Field) {
    val modifiersField = Field::class.java.getDeclaredField("modifiers")
    modifiersField.isAccessible = true
    modifiersField.setInt(fGson, fGson.modifiers and Modifier.FINAL.inv())
}

// etc
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.