Boolean型で定義しているフォームの項目に対してnullが送られてきた場合にfalseに変換して受け取りたいことがあり、調べたことを備忘録として残していく。
前提
- Spring Framework 3.0.2
- Java 17
PropertyEditor
Spring Frameworkでは、リクエストとして送られてきたパラメータをオブジェクトに変換する際やオブジェクトを文字列にシリアライズする際に、PropertyEditor
を使ってオブジェクト→文字列, 文字列→オブジェクトの変換を行なっている。
PropertyEditorは指定した型のプロパティ値を編集できるようにするためのサポートを提供するクラス。
Springが提供しているものではなく、Javaが提供しているインターフェースである。
またその基本実装クラスであるPropertyEditorSupport
もJavaが提供していて、このクラスをSpring Framework側で拡張して、さまざまなPropertyEditorを提供している。
PropertyEditor (Java SE 17 & JDK 17)
PropertyEditorSupport (Java SE 17 & JDK 17)
例えば、Collection型に対するPropertyEditorとしてCustomCollectionEditor
が提供されていたり、Integer型に対してCustomNumberEditor
が提供されていたりする。
具体的にデフォルトでどの型に対してどのPropertyEditorが実行されるのかは、以下の処理で記載されている。
また、独自のPropertyEditorを作ることもでき、その場合はPropertyEditorSupportを継承してクラスを実装する。 以前書いた以下の記事で、Collection型や文字列型の独自PropertyEditorの例を説明している。
今回はBoolean型に対するPropertyEditorであるCustomBooleanEditor
を継承した独自PropertyEditorを実装して変換を行う。
CustomBooleanEditor
CustomBooleanEditorは、コンストラクタで以下3つのパラメータを指定できる。
- allowEmpty:空文字を許容するか。許容する場合、入力値をnullに変換してフォームの項目にセットする。
- trueString:trueとして扱いたい文字列。nullを指定した場合、"true", "yes", "on", "1"という文字列のみtrueとして扱う。(大文字/小文字は無視)
- falseString:falseとして扱いたい文字列。nullを指定した場合、"false", "no", "off", "0"という文字列のみtrueとして扱う。(大文字/小文字は無視)
new CustomBooleanEditor("真", "偽", true)
例えば、↑のようなCustomBooleanEditorのインスタンスを生成した場合、以下のようなロジックで文字列を変換する。
- 空文字が送られてきた場合、nullに変換する
- "真"という文字列が送られてきた場合、trueに変換する
- "偽"という文字列が送られてきた場合、falseに変換する
- 上記以外の文字列が送られてきた場合、IllegalArgumentExceptionをthrowする
独自PropertyEditor
CustomBooleanEditorを継承した独自PropertyEditorを実装し、以下のロジックで変換を行う。
- 空文字を許容しない
- "true", "yes", "on", "1"という文字列が送られてきた場合、trueに変換する
- "null", "false", "no", "off", "0"という文字列が送られてきた場合、falseに変換する
- 上記以外の文字列が送られてきた場合、IllegalArgumentExceptionをthrowする
実装した独自PropertyEditorは以下。
package com.daisuzz.samplepropertyeditor.propertyeditor; import org.springframework.beans.propertyeditors.CustomBooleanEditor; import org.springframework.lang.Nullable; public class NullSupportCustomBooleanEditor extends CustomBooleanEditor { public NullSupportCustomBooleanEditor(boolean allowEmpty) { super(allowEmpty); } @Override public void setAsText(@Nullable String text) throws IllegalArgumentException { String input = (text != null ? text.trim() : null); if ("null".equalsIgnoreCase(input)) { setValue(Boolean.FALSE); return; } super.setAsText(text); } }
Boolean型にバインドしたいので、WebDataBinderを使って登録処理を行う。
@InitBinder public void initBinder(WebDataBinder binder) { binder.registerCustomEditor(Boolean.class, new NullSupportCustomBooleanEditor(false)); }
サンプルコードは以下
https://github.com/daisuzz/spring-sandbox/tree/main/sample-property-editor
実際にアプリケーションを立ち上げてリクエストを送ってみるとnullがfalseに変換されていることが確認できた。
$ curl -XGET "http://localhost:8080/person?age=20&canVote=null" {"age":20,"canVote":false}