1. 概要

この短いチュートリアルでは、SpringMVCでJSONパラメーターを操作する方法を詳しく見ていきます。

まず、JSONパラメーターの背景について少し説明します。 次に、うさぎの穴を掘り下げて、POSTおよびGETリクエストでJSONパラメーターを送信する方法を確認します。

2. SpringMVCのJSONパラメーター

JSON を使用してデータを送受信することは、Web開発者の間で一般的な方法です。 JSON文字列の階層構造は、HTTPリクエストパラメータを表すためのよりコンパクトで人間が読める方法を提供します。

デフォルトでは、Spring MVCは、Stringなどの単純なデータ型にすぐに使用できるデータバインディングを提供します。 その目的のために、内部で組み込みのプロパティエディタのリストを使用します。

ただし、実際のプロジェクトでは、より複雑なデータ型をバインドしたい場合があります。 たとえば、JSONパラメーターをモデルオブジェクトにマップできると便利な場合があります。

3. POSTでJSONデータを送信する

Springは、POSTリクエストを介してJSONデータを送信する簡単な方法を提供します。 組み込みの@RequestBodyアノテーションは、リクエスト本文にカプセル化されたJSONデータを特定のモデルオブジェクトに自動的に逆シリアル化できます。

一般に、リクエスト本文を自分で解析する必要はありません。 Jacksonライブラリを使用して、すべての面倒な作業を行うことができます

それでは、SpringMVCでPOSTリクエストを介してJSONデータを送信する方法を見てみましょう。

まず、渡されたJSONデータを表すモデルオブジェクトを作成する必要があります。 たとえば、Productクラスについて考えてみます。

public class Product {

    private int id;
    private String name;
    private double price;

    // default constructor + getters + setters

}

次に、POSTリクエストを受け入れるSpringハンドラーメソッドを定義しましょう。

@PostMapping("/create")
@ResponseBody
public Product createProduct(@RequestBody Product product) {
    // custom logic
    return product;
}

ご覧のとおり、製品引数に@RequestBodyアノテーションを付けるだけで、クライアントから送信されたJSONデータをバインドできます

これで、cURLを使用してPOSTリクエストをテストできます。

curl -i \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-X POST --data \
  '{"id": 1,"name": "Asus Zenbook","price": 800}' "http://localhost:8080/spring-mvc-basics-4/products/create"

4. GETでJSONパラメーターを送信する

SpringMVCは@RequestParamを提供して、GETリクエストからクエリパラメーターを抽出します。 ただし、 @RequestBodyとは異なり、 the @RequestParam アノテーションは、intStringなどの単純なデータ型のみをサポートします。

したがって、JSONを送信するには、JSONパラメーターを単純な文字列として定義する必要があります。

ここでの大きな問題は、JSONパラメーター( String )をProductクラスのオブジェクトにどのように変換するかです。

答えはとても簡単です! Jacksonライブラリが提供するObjectMapperクラスは、JSON文字列をJavaオブジェクトに変換する柔軟な方法を提供します

それでは、SpringMVCでGETリクエストを介してJSONパラメーターを送信する方法を見てみましょう。 まず、GETリクエストを処理するために、コントローラーに別のハンドラーメソッドを作成する必要があります。

@GetMapping("/get")
@ResponseBody
public Product getProduct(@RequestParam String product) throws JsonMappingException, JsonProcessingException {
    Product prod = objectMapper.readValue(product, Product.class);
    return prod;
}

上記のように、 readValue()メソッドを使用すると、JSONパラメーターproductProductクラスのインスタンスに直接逆シリアル化できます。

JSONクエリパラメータをStringオブジェクトとして定義していることに注意してください。 では、 @RequestBody を使用したときのように、Productオブジェクトを渡したい場合はどうでしょうか。

この質問に答えるために、Springはカスタムプロパティエディターを通じて簡潔で柔軟なソリューションを提供します。

まず、文字列として指定されたJSONパラメーターをProductオブジェクトに変換するロジックをカプセル化するカスタムプロパティエディターを作成する必要があります

public class ProductEditor extends PropertyEditorSupport {

    private ObjectMapper objectMapper;

    public ProductEditor(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    @Override
    public void setAsText(String text) throws IllegalArgumentException {
        if (StringUtils.isEmpty(text)) {
            setValue(null);
        } else {
            Product prod = new Product();
            try {
                prod = objectMapper.readValue(text, Product.class);
            } catch (JsonProcessingException e) {
                throw new IllegalArgumentException(e);
            }
            setValue(prod);
        }
    }

}

次に、JSONパラメーターをProductクラスのオブジェクトにバインドしましょう。

@GetMapping("/get2")
@ResponseBody
public Product get2Product(@RequestParam Product product) {
    // custom logic
    return product;
}

最後に、パズルの最後の欠けている部分を追加する必要があります。 SpringコントローラーにProductEditorを登録しましょう。

@InitBinder
public void initBinder(WebDataBinder binder) {
    binder.registerCustomEditor(Product.class, new ProductEditor(objectMapper));
}

安全なトランスポートを確保するには、JSONパラメーターをURLエンコードする必要があることに注意してください。

したがって、代わりに:

GET /spring-mvc-basics-4/products/get2?product={"id": 1,"name": "Asus Zenbook","price": 800}

送信する必要があります:

GET /spring-mvc-basics-4/products/get2?product=%7B%22id%22%3A%201%2C%22name%22%3A%20%22Asus%20Zenbook%22%2C%22price%22%3A%20800%7D

5. 結論

要約すると、SpringMVCでJSONを操作する方法を見ました。 その過程で、POSTおよびGETリクエストでJSONパラメーターを送信する方法を紹介しました。

いつものように、例の完全なソースコードは、GitHubから入手できます。