Search code examples
jsonkotlingson

How to enforce strong type enforcement in Gson?


I am using Gson to parse JSON. What surprised me is that if I have a field of type String in my POJO class and I have a number in JSON it's parsed correctly without throwing an exception. Similarly the other way - I wrote this test to illustrate:

    data class Parsed(
        val testString: String,
        val testNumber: Int,
    )

    @Test
    fun `test gson type parsing`() {
        val gson = Gson()

        val json = "{ \"testString\" : 1, \"testNumber\" : \"1\"}"

        val parsed = gson.fromJson(json, Parsed::class.java)

        assertThat(parsed.testString).isEqualTo("1") // passes
        assertThat(parsed.testNumber).isEqualTo(1) // passes
        // expected an exception because number is parsed into a string field and string is parsed into number
    }

Is there any way to change this behavior? (Only found setLenient() on GsonBuilder but it's not related to this)


Solution

  • I don't think you can turn of type coercion in gson. Your best bet would probably be to write a custom deserializer that prevents this.

    That being said, contemplate not using gson in kotlin code as it completely circumvents the null safety of the language. You are better of using a serialization framework that is kotlin aware, such as jackson (with kotlin plugin) or kotlinx-serialization.

    Aditionally it seems like jackson allows to turn this specific type coercion off, using this flag: https://fasterxml.github.io/jackson-databind/javadoc/2.9/com/fasterxml/jackson/databind/MapperFeature.html#ALLOW_COERCION_OF_SCALARS

    Kotlinx-serialization seems to not have such an option: https://github.com/Kotlin/kotlinx.serialization/issues/1042