標準APIの仕様に関して

TemPlat Consoleでは、Open API(Swagger)に準拠したAPIを生成しています。(※OpenAPIとは、RESTful APIを記述するためのフォーマットのことで、Swagger 2.0を拡張して実装されています)

ここでは、そのAPIの仕様と呼び出し方を解説します。

TemPlatで作成される標準API仕様とは

TemPlat ConsoleでERDを作成してビルドすると、上記の動画で説明したようにSwagger UIを使ってAPIを確認することができます。ここではこの標準で作成されるAPIの仕様に関して説明します。

標準APIとしてはERDで作成した各テーブル毎に以下のAPIが作成されます。ここでは例として「Project」テーブルを例にして記載します。

API種類HTTP MethodURLパス補足説明
1.検索GET/projects検索条件に一致するレコードの一覧を取得
2.件数取得GET/projects/count検索条件に一致する件数を所得する
3.キー取得GET/project/{id}キー指定で1件取得
4.登録POST/project指定した内容で新規登録
5.更新PUT/project/{id}指定した内容で全項目を更新
6.部分更新PATCH/project/{id}特定の項目のみ更新
7.削除DELETE/project/{id}指定したキーで1件削除

ここでいくつか補足説明をします。

検索系APIの検索条件に関して

初期生成される検索API(1.検索と2.件数取得)では、テーブルの各カラムをイコール条件とした検索条件を指定することができます。複数カラムの条件を指定した場合には、AND条件(すべての条件に一致する)ものだけが取得されます。

検索条件はAPIのソースコードをカスタマイズすることで拡張することができます。検索条件に関しては、採用するデータベース(KVSのDatastoreまたは、RDBのCloudSQL)によって、指定できる内容に制限があります。

標準APIの呼び出し方法

Swagger UIによる呼び出し

ERDを作成してビルドするとすぐにSwagger UIのWebページからAPIを呼び出すことができます。実際にAPIの動きを確認したり、テスト用データを作りたいときとかに利用できます。以下の動画で確認までの流れを解説していますので、まずはご確認ください。

OpenAPIによる呼び出し

通常のシステムではAPIを呼び出すクライアントアプリがあると思います。これらのクライアントアプリ向けに、TemPlat Consoleでは、現在JavaScript(Type Script)用のクライアントモジュールも自動生成しています。クライアントモジュール生成には、Open API Generatorを使用しています。

TemPlat ConsoleではGCP上のgitに準拠したソース管理環境(Google Source Repository:GSR)に、ソース管理のプロジェクトを自動作成します。現在このプロジェクトは以下のようにAPIに加え、クライアントアプリとして、スマホアプリ(ReactNative)、Webクライアント(Nuxt.js)のプロジェクトを作成しています。クライアントモジュールはAPIをビルドすると同時にこれらのクライアントアプリのプロジェクトに同期してソースが生成されています。

クライアントアプリを開発する場合には、これらのソースプロジェクトをcloneすることで、すぐにAPIを呼び出す準備ができています。

GSRのリポジトリはTemPlat Consoleの上記の「ソースリポジトリに移動」にリンクからアクセスできます。アクセスすると以下のように3種類のプロジェクトが作成されています。そのうちのスマホアプリ用プロジェクトとWebアプリ用プロジェクトに、OpenAPI Generatorにより生成されたAPIアクセス用のクライアントが生成されています。

実際のリポジトリ内のソースツリーを見ると以下のようになっています。以下は、スマホアプリ用のプロジェクトに追加されたAPIクライアントの例になります。ReactNative用のプロジェクト構成の中にAPIクライアントが自動で追加されています。

以下がWebクライアント用のプロジェクトに生成されたAPIクライアントの場合です。

このプロジェクトをgitクライアントを使用して開発環境にcloneすればすぐにAPI呼び出しができます。では、具体的なソースを見ていきましょう。

API呼び出しソースの書き方

ここではWebクライアント(Nuxt.jsベースになります)での、ソースの例を見ていきたいと思います。ここでは商品(Product)テーブルに対して自動生成されているAPIの呼び出しを例に説明していきます。ERDとしては以下のようになっています。

まずは、Open API GeneratorによりプロジェクトにあるAPIクライアントをimportします。importはAPIの呼び出し関数が実装されている「ProductApi(テーブル名+APIという命名になっています)」と、データ構造を定義している「ModelProduct(Model+テーブル名という命名になっています)」を使います。

このModelProductには上記ERDのProductテーブルの各フィールドが定義されており、このModelに値を詰めてAPIへ渡して登録・更新したり、逆に検索系では、APIのレスポンスとしてこれらのModelが取得できるようになっています。クライアント側でのデータ管理にもこのModelを利用することもできます。

import {
  ProductApi,
  ModelProduct,
} from '~/apis'

それでは実際のAPI呼び出し部分のコードを見ていきたいと思います。

検索APIの呼び出し

まずは検索APIの呼び出しです。SwaggerUI上では以下のAPIに該当します。

以下の例は単純にAPIからProductテーブルの全件を取得するコードです。API呼び出し用のProductAPIをnewして、その関数として用意されている「searchProduct()」という関数を引数無しで呼ぶことで全件取得ができます。

products: ModelProduct[] = []

async search() {
  this.products = await new ProductApi().searchProduct()
    .then(res => res.data.products) || []
}

参照APIの呼び出し

サンプルコードは以下となります。

const productID = 12345
let editedEntry: ModelProduct = {}

editedEntry = 
  await productApi.getProduct(productID)
    .then( res => res.data) || {}

登録APIの呼び出し

Swagger上ではPOSTメソッドで呼び出されるAPIとなります。

サンプルコードは以下となります。

let editedEntry: ModelProduct = {}

editEntry = {
  productName: '商品名',
  productCode: 'PRD-0001',
  description: '商品説明'
}

editedEntry = 
  await productApi.createProduct(editedEntry)
    .then( res => res.data) || {}

更新APIの呼び出し

更新APIには2種類あるので、まずはその違いから説明します。SwaggerUIでは以下の2つ(PUTメソッドとPATCHメソッド)が更新用のAPIとなります。

PUTメソッドの場合(APIの関数ではupdateProduct)には、リクエストで渡したModel(ここではModelProduct)に渡した全項目でデータベースのレコードを更新します。

注意事項としては、同一レコードを複数のクライアント(ユーザー)が同時に変更する頻度が高い場合に、実際に変更した項目以外に関して他のユーザの更新を上書きしてしまう可能性があります。

これに対してPATCHメソッドの場合(APIの関数ではpatchProduct)は、設定した項目だけデータベースを更新することができるので、その他の更新不要な項目が裏で変更されていても影響がありません。

ですので、データモデル(複数のユーザが更新し合うテーブルか?)や、更新頻度や更新方式によって、この2つのメソッドを使い分けてください。

PUTメソッドによる更新(全項目更新)

サンプルコードは以下となります。

let editedEntry: ModelProduct = {}

// APIでProductをID指定で取得
editedEntry = 
  await productApi.getProduct(productID)
    .then( res => res.data) || {}

// 一部の項目を更新
editedEntry.description = '修正した商品説明'

// Model全部を渡して更新API呼び出す
editedEntry = 
  await productApi.updateProduct(
    editedEntry.id,
    editedEntry
  ).then( res => res.data) || {}

PATCHメソッドによる更新(部分項目更新)

サンプルコードは以下となります。

let editedEntry: ModelProduct = {}
let updateEntry: ModelProduct = {}

// APIでProductをID指定で取得
editedEntry = 
  await productApi.getProduct(productID)
    .then( res => res.data) || {}

// 更新用のモデルを別で作って、変更したい項目だけ設定する
updateEntry = {
  description: '修正した商品説明'
}

// Model全部を渡して更新API呼び出す
editedEntry = 
  await productApi.patchProduct(
    editedEntry.id,
    updateEntry
  ).then( res => res.data) || {}

削除APIの呼び出し

サンプルコードは以下となります。シンプルにIDを引数にAPIを呼び出すだけです。

const productID = 12345
await productApi.deleteProduct(productID)