Works by

Ren's blog

アプリケーションバックエンド中心に書いていきます

【Spring】JSONリクエストのBoolean型以外のパラメータを暗黙的にBooleanに変換させない

f:id:rennnosukesann:20181220183020p:plain:w400

Spring2ではJSONリクエスト/レスポンスボディのマッピングの際、Boolean型メンバに非Booleanの値をマッピングしようとしたときに正常に処理を終えてしまいます。
例えば、"1" や "true" という文字列を渡してもtrueに変換され、 "0" や "false" 文字列を渡すとfalseに変換されるといった塩梅です。

これは fasterxml/Jacksonのデフォルト仕様で 、このマッピングを防ぐにはSpringで使用されるObjectMapperの設定を修正する必要があります。

環境

  • Kotlin: 1.3.21
  • Spring: 2.1.4 RELEASE
  • JDK : OpenJDK11.0.2

ソースはKotlinです。

Deserializerを定義

JSONリクエストパラメータをKotlin内オブジェクトにマッピングする際の規則を明示的に記述する Deserializer クラスを定義します。

BooleanDeserializer
class BooleanDeserializer : JsonDeserializer<Boolean>() {
    // JSONパラメータをBooleanにマッピングしようとすると呼ばれる
    override fun deserialize(jsonParser: JsonParser, ctxt: DeserializationContext): Boolean {
        return jsonParser.booleanValue // booleanValue : booleanでない値のときに参照されるとJsonParseError
    }
}

deserialize メソッドはJSONパラメータをBooleanにマッピングしようとすると呼ばれます。このとき、 booleanでない値をマッピングしようとするとJsonParseErrorが呼ばれるので、制御したい場合は適宜ハンドリングしてください。

DeserializerをObjectMapperに適用する

次に作成したDeserializerをSpringが使用するObjectMapperに設定し、前述の変換規則が適用されるようにします。

JsonConfig
@Configuration
class JsonConfig {

    @Bean
    fun objectMapperBuilder(): Jackson2ObjectMapperBuilder {
        val builder = Jackson2ObjectMapperBuilder()
        return builder
    }

    @Bean
    fun objectMapper(): ObjectMapper {
        val objectMapper = objectMapperBuilder().build<ObjectMapper>()
        objectMapper.registerModule(createModule())
        return objectMapper
    }

    private fun createModule(): Module {
        val module = SimpleModule()
        // boolean型以外を暗黙的に許可しない
        module.addDeserializer(Boolean::class.java, BooleanDeserializer())
        return module
    }

}

Springで使用される ObjectMapper 及び ObjectMapperBuilderを、@Bean 宣言したメソッドで上書きしています。 さらに createModule() 内で BooleanDecelializer を登録した Module オブジェクトを生成し、それを ObjectMapper に登録しました。