概要
Spring Bootで従来までのControllerをRestContorllerに変更した際に、これまでInitBinderで設定していたStringTrimmerEditorの設定が効かなくなってしまいました。
これは入力データを処理する仕組みがRestController(@RequestBody)ではJacksonで処理されるためです。
サンプルはKotlinで記述していますが、Javaでも基本的に同じです。
設定ファイル(application.yml)で設定を試みる
application.ymlにてそれっぽい設定項目を発見し、試してみました。
jackson:
deserialization:
ACCEPT_EMPTY_STRING_AS_NULL_OBJECT: true
が、、、いろいろ試しましたが、うまくいきませんでした。
変換先がPOJOじゃないとだめみたいです。
解決方法
結局設定ファイルではうまくいかず、Stringを変換する独自Deserializerを作成しObjectMapperに設定することにしました。
1. Deserializerクラスの作成
JsonDeserializerを継承してクラスを作成しても良かったのですが、標準で設定されているStringDeserializerの中身を見てみるとそれなりに処理が書かれていたので、StringDeserializerを継承してクラスを作成することにしました。
package ...
import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.deser.std.StringDeserializer
class EmptyToNullStringDeserializer : StringDeserializer() {
override fun deserialize(p: JsonParser, ctxt: DeserializationContext): String? {
val result = super.deserialize(p, ctxt)
return if(result.isNotEmpty()) result else null
}
}
スーパークラスの返した値を最終行で空文字かチェックしているだけの処理となります。
2. ObjectMapperへの登録
適当なConfigクラスを生成(すでにあるものに追加してもOK)しObjectMapperのBeanを定義します。
package ...
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder
@Configuration
class JacksonConfig {
@Bean
fun jacksonBuilder(): Jackson2ObjectMapperBuilder {
return Jackson2ObjectMapperBuilder()
.deserializerByType(String::class.java, EmptyToNullStringDeserializer())
}
}
以上です。
まとめ
簡単な設定に見えて結構はまってしまいました。
普段は何も考えずにJacksonを使っているのですが、もう少し勉強が必要な気がします。