3

I have the next peace of code

    @Test
    fun `simple test`() {
        val objectMapper = ObjectMapper()
            .setSerializationInclusion(JsonInclude.Include.NON_NULL)
            .setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE)
            .registerModule(KotlinModule())

        val value = objectMapper.writeValueAsString(MyClass(myField1 = "something", myField2 = "something2"))
        assertNotNull(value)
    }

    data class MyClass (
        val myField1: String? = null,
        @JsonProperty("my_field_2")
        val myField2: String? = null,
    )

the result of deserialization is next

{"my_field1":"something","my_field_2":"something2"}

Is it possible to configure objectMapper to automatically populate _ value, before digits in object property names, without specifying it in @JsonProperty?

user2105282
  • 724
  • 1
  • 12
  • 26

1 Answers1

1

Yes, this is possible using a PropertyNamingStrategy:

objectMapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE)

Note that you named your snake-case fields inconsistently, because there is my_field1 without a _ before the digit, and my_field_2 with a _ before the digit. The configuration above using PropertyNamingStrategies.SNAKE_CASE works fine for the first naming (like in my_field1).

If you want to use the second naming (like in my_field_2), then you would have to write your own naming strategy like this:

class MySnakeCaseStrategy : NamingBase() {
    override fun translate(input: String?): String? =
        if (input == null) null
        else "([A-Z]+|[0-9]+)".toRegex().replace(input) { "_${it.groupValues[1]}".lowercase() }
}

That naming strategy can then be used to configure your object-mapper:

objectMapper.setPropertyNamingStrategy(MySnakeCaseStrategy())

I do not know if and how it would be possible to support both naming strategies at the same time.

Karsten Gabriel
  • 3,115
  • 6
  • 19
  • Nice trick, I guess it should be modified a little bit if we want to support two digits as well. For example `myField11` – user2105282 Mar 25 '22 at 09:18
  • @user2105282 I changed the regex to match several uppercase letters or numbers in a row, making it also possible to match something like `myURI12` with `my_uri_12`. There are still cases where this would fail, like e.g. `myURLisCool` would match `my_urlis_cool` and not `my_url_is_cool` as one would expect. It would generally be better to not use a regex, but to parse it manually. But for the sake of brevity of the answer, I think it is okay to have a more easily readable naming strategy without too much details. – Karsten Gabriel Mar 25 '22 at 09:30