はじめに
業務上、ETLやEAIツールでAPIからのデータをパースするのに、JSON Schemaでどんな項目があるかを事前定義するJSON Schemaファイルを作成する必要がありました。
pythonで項目一覧をinputにKintoneのレコード一括取得APIのJSON Schemaを生成するプログラムを作りました。
※JSON Schemaに関する説明は本記事では割愛しております。
作りたいもの
Kintoneのフィールドコード一覧を元にKintoneレコード一括取得API用のJSONスキーマを作成する。
Input
Kintoneのフィールドコード一覧
会社名,部署名,担当者名
Output
Kintone REST APIの レコード一括取得のJSON Schemaファイル
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"records": {
"type": "array",
"items": {
"type": "object",
"properties": {
"会社名": {
"type": "object",
"properties": {
"value": {
"type": "string"
}
}
},
"部署名": {
"type": "object",
"properties": {
"value": {
"type": "string"
}
}
},
"担当者名": {
"type": "object",
"properties": {
"value": {
"type": "string"
}
}
}
}
}
},
"totalCount": {
"type": "string"
}
}
}
状況
- JSONをJSON Schemaに変換するのは、Webサイト(https://jsonschema.net/#/ )等の使っていますが、今回は元のJSONがなく使えない。
- Kintone上のフィールドコード一覧の情報のみ
- APIの仕様は、KintoneのDeveloperサイトで確認可能。
- jsl(https://jsl.readthedocs.io/en/latest/tutorial.html) というpythonのライブラリを使えば、実装できそう
やってみた
以下のプログラムで実現できました。
import jsl # https://jsl.readthedocs.io/en/latest/tutorial.html
import json
fieldCodeList = ["会社名","部署名","担当者名"]
outputPath = r"KintoneGetRecordsSchema.json"
class Root(jsl.Document):
class Options(object): #オプション設定箇所
description = 'XXアプリのKinton一括取得API'
records = jsl.ArrayField(jsl.DocumentField(Record))
totalCount = jsl.StringField()
class Record(jsl.Document):
localNameSpace = locals()
# https://novnote.com/variable-string/442/ String値を変数に変換
for fieldCode in fieldCodeList:
localNameSpace[fieldCode] = jsl.DocumentField(Field)
class Field(jsl.Document):
value = jsl.StringField()
jsonSchema = json.dumps(Root.get_schema(ordered=True), indent=3).encode().decode('unicode-escape')
# https://note.nkmk.me/python-unicode-escape/ #日本語フィールドがUnicodeエスケープされたバイト列になってしまうので、変換
f = open(outputPath, "w", encoding='utf-8')
f.write(jsonSchema)
f.close()
説明
- JSON Schemaの階層ごとにクラスを定義する必要がありました。
- Rootクラスで最上位層のプロパティを定義しています。
- Recordsプロパティは、Recordクラスの配列として定義しています。
- 各RecordクラスでInputのフィールドコード一覧をプロパティ化しています。
- 各フィールドコードは、全てstringと定義しました。※jsl.StringField()の箇所です。
第1関門
inputの配列(会社名,部署名,担当者名)のStringのデータを変数名に変換しないといけない。
⇒locals関数を使うことで実現できました。
今回のコードでは、[会社名]、[部署名]、[担当者名]という3つの変数を作っています。
※日本語の変数名が使えるんですね~
第2関門
JSON出力時に日本語フィールドコードが、Unicodeエスケープされたバイト列に変換されてしまう。
⇒.encode().decode('unicode-escape')関数で、バイト列に一度エンコードし、
Unicodeエスケープされていない文字列にデコードすることで解消できました。
課題
生成したJSON Schemaファイルを見ると、各層にadditionalProperties:falseというプロパティが作られていました。今回は不要なプロパティで可視性が悪くなるため、出力しないようにしたかったのですが、これはライブラリの仕様上できませんでした。
さいごに
今回は全てのフィールドコードをstringにしたので、シンプルなプログラムとなりましたが、厳密なスキーマ定義が必要な場合は、もっと複雑なプログラムになりそうです。