コンピュータクワガタ

かっぱのかっぱによるコンピュータ関連のサイトです

Spring MVC 3.2によるJSONのValidation

Spring 4.0が出ていますが、3.2の話題です。

Spring MVC 3.2から@RequestBodyに対しても@Validが使え、JSONオブジェクトに対してvalidationをかけることができます。 ドキュメントは 4.11参照

具体的な手順です。今回は、以下のようなJSONを例に取ります。

{
  bookId: 書籍ID(文字列)
  bookName: 書名(文字列)
  price: 価格(数値)
}

これに対して、対応するModelを以下のようにJavaで定義します。

class Book {
    @NotBlank
    @Length(max = 5)
    private String bookId;

    @NotBlank
    @Length(max = 10)
    private String bookName;

    // Integer、intにはNotNullはできない
    @NotNull
    @Min(1)
    private int price;

    // getter、setter省略
}

コントロールの実装は、以下のようにします。JSONを受け取る@RequestBodyのついた引数に@Validをつけることができます。

@RequestMapping(value = "/books", method = RequestMethod.POST,
     consumes = MediaType.APPLICATION_JSON_VALUE, 
     produces = MediaType.APPLICATION_JSON_VALUE
        + ";charset=utf-8")
@ResponseBody
public Book insert(@RequestBody @Valid Book book, Errors errors) {
    for (ObjectError oe : errors.getAllErrors()) {
       System.out.println(oe.getDefaultMessage());
    }

    bookList.add(book);
    return book;
}

通常のValidationと同様に、@Validアノテーションを付けるだけで、引数のerrorsオブジェクトにエラーが格納されます。

上記の例では、そのエラーメッセージを出力しています。

ただし、通常のValidationと違い型が異なる場合には、エラーがerrorsオブジェクトに格納されずに、HttpMessageNotReadableExceptionが発生します。その場合、リクエストに対するレスポンスは400エラーになります。

数値の項目に数値変換できない文字列が入ってきた際にチェックするためには、例外ハンドラを設定する必要があります。

ここではアノテーションにより例外ハンドラをコントローラクラスの中に作成します。

@ExceptionHandler(HttpMessageNotReadableException.class)
@ResponseBody
public Book handleException(HttpMessageNotReadableException ex,
        WebRequest request) {
    Throwable t = ex.getCause();
    if (t != null && t instanceof InvalidFormatException) {
        InvalidFormatException ife = (InvalidFormatException) t;
        // エラーのフィールド。
        for (Reference r : ife.getPath()) {
            System.out.println(r.getFieldName());
        }
        // エラーになったフィールドの型
        System.out.println("type= " + ife.getTargetType().getName());
        // エラーになったフィールドの値
        System.out.println("value=" + ife.getValue());
    }

    return new Book();
}

HttpMessageNotReadableExceptionからgetCaouseしてInvalidFormatExceptionを取得します。InvalidFormatExceptionからエラーのあったフィールドの情報を取得することができます。

Spring3入門 ――Javaフレームワーク・より良い設計とアーキテクチャ

Spring3入門 ――Javaフレームワーク・より良い設計とアーキテクチャ