👻
FreeFormatなJSONをREST APIのパラメータとして扱う
Java、Swagger、SpringBootを利用した構成で、REST APIのパタメータとしてFreeFormatなJSONを扱う方法を記載します
swagger.yamlで動的なJSONを表現する
definitions:
Product:
type: "object"
additionalProperties:
type: object
additionalProperties
を追加することで、自動生成したJavaコードではProductの型がHashMap<String, Object>
となりJSONのKey、Valueと同等な感じで扱えるようになります
APIでどう扱うか
GET APIでパスパラメータとしてフリーフォーマットなJSONを文字列で受け取り処理する
objectMapper.readValue
でSwaggerで自動生成されたProduct.class
にマッピングできる
@Override
public ResponseEntity<Response> find(
@Valid String query,
@Valid Integer offset,
@Valid Integer limit
) {
Response res = new Response();
List<Product> products = new ArrayList<>();
// queryはデータ取得処理でそのまま使う
// データ取得処理で何かしら配列のオブジェクトを入手
for (Hoge product : datalist) { // ここはDBによってloopの回し方変わりそう
// HogeをjsonStrにする処理をここに書く
products.add(objectMapper.readValue(new StringReader(jsonStr), Product.class));
}
res.setProducts(products);
return ResponseEntity.ok(res);
POST APIでBodyとしてフリーフォーマットなJSONを受け取り処理する
リクエストの想定
$ curl -XPOST localhost:8080/products \
-H "Content-Type: application/json" \
-d '{"device":["ps4","pc"],"title": "hogeGame","info": {"x": 2, "y": 1}}'
リクエスト時にbodyにフリーフォーマットなJSONを要求、insertメソッドではMap<String, Object> body
にコンバートされ、以下の例ではJSON文字列に加工している
@Override
public ResponseEntity<Void> insert(@Valid Map<String, Object> body) {
String insertQuery = getObjectMapper().get().writeValueAsString(body);
swagger例
swagger.yaml
~~ 略 ~~
paths:
/product:
get:
parameters:
- name: "query"
in: "query"
required: false
type: "string"
- name: "offset"
in: "query"
required: false
type: "integer"
- name: "limit"
in: "query"
required: false
type: "integer"
responses:
"200":
schema:
$ref: "#/definitions/Response"
post:
parameters:
- name: "document"
in: "body"
required: true
schema:
$ref: "#/definitions/Product"
~~ 略 ~~
definitions:
Product:
type: "object"
additionalProperties:
type: object
Response:
type: "object"
properties:
products:
type: "array"
items:
$ref: "#/definitions/Product"
offset:
type: "integer"
limit:
type: "integer"
Discussion