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 Answer 1

2
\$\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\$

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.