😸

ChatGPTにデータ構造を一括でチェックするプログラムを組んで欲しい

2023/03/13に公開

データ構造を一括でチェックしたい

要求

ざっくり以下のような事を思いついたものとする。

あ〜、一括で変換したデータのデータ構造が意図したものになっているかをチェックしたいなー。

要件

要求から要件に分解していく。

JSONバリデーション

前項 データシートを元にして構造化されたJSONを生成したい で利用した構造を再利用する。
また、JSON構造テストは JSON Schema を利用してバリデーションをするようにしたい。

JSONデータ構造
{
  "period": "年代",
  "artist": "アーティスト名",
  "trackList": [
    { "name": "曲名", "date": "リリース日", "bpm": "BPM" }
  ]
}

細かい要件

  • (たまには)
    Pythonでやりたい
  • 第二引数でZipファイルを指定したい
  • Zipファイルに含まれるJSON全てをテストしたい
  • エラーがあった箇所とエラーの原因を知りたい

要件をプロンプトに落とし込む

プロンプトに落とし込むには、要件を詳記する必要がある。

JSONバリデーション

JSONバリデーションは前回抽象化した構造と、プロンプトでの指定の明示で対応できる。

プロンプト
- JSON構造をJSON Schemaに変換したい

細かい要件

それぞれプロンプト向けの文言に直す。
引数の指定方法は指定ブロックをまとめると取りこぼしやすいため、別のブロックに分けた。

プロンプト
処理
- Pythonコード全体が欲しい
- 指定したZipファイルに含まれるJSONを再帰的に探したい
- 見つかったJSON全てがスキーマに一致するかテストしたい
- エラーを `{ファイルパス} [{(取得出来れば)プロパティ名}]: {エラー文}` の形で知りたい

呼び出し方法
- コマンドの第一引数でZipファイルのパスを指定したい

最終的なプロンプト

プロンプト化した要件をまとめると、以下のような表現となる。

整えたプロンプト
次の条件に従ってJSONの構造が正しいかを確認するPythonコードがほしい。

テスト基準となるJSONデータ構造

```
{
  "period": "年代",
  "artist": "アーティスト名",
  "trackList": [
    { "name": "曲名", "date": "リリース日", "bpm": "BPM" }
  ]
}
```

処理
- Pythonコード全体が欲しい
- JSON構造をJSON Schemaに変換したい
- 指定したZipファイルに含まれるJSONを再帰的に探したい
- 見つかったJSON全てがスキーマに一致するかテストしたい
- エラーを `{ファイルパス} [{(取得出来れば)プロパティ名}]: {エラー文}` の形で知りたい

呼び出し方法
- コマンドの第一引数でZipファイルのパスを指定したい

動作確認

ChatGPTから返却のあったコードを実行してみる。

生成されたコードではライブラリを利用しているため、インストールしておく必要がある。

% pip install zipfile jsonschema
% python json_validator.py data.zip
data.zip/1990/犬.json [deque(['trackList', 0, 'date'])]: 19940401 is not of type 'string'

Failed validating 'type' in schema['properties']['trackList']['items']['properties']['date']:
    {'type': 'string'}

On instance['trackList'][0]['date']:
    19940401

... 中略 ...

data.zip/2010/猿.json [deque(['trackList', 0, 'date'])]: 20190909 is not of type 'string'

Failed validating 'type' in schema['properties']['trackList']['items']['properties']['date']:
    {'type': 'string'}

On instance['trackList'][0]['date']:
    20190909

全ファイルで "date" 値が文字列ではない というエラーになっている。
比較してみると、Pythonコード中のスキーマ定義は "date" 値と "bpm" 値を文字列だと解釈しているのに対し、変換ツールで変換したJSONは "date" 値と "bpm" 値を数値として扱っている。

スキーマ定義部分
"properties": {
  "name": {"type": "string"},
  "date": {"type": "string"},
  "bpm": {"type": "string"}
},
ツールで変換後のJSON
{
  "name": "遠吠えA",
  "date": 19940401,
  "bpm": 80
}

補完

利用想定上では "date" 値と "bpm" 値が数値のままでも問題は無いため、チェッカー側のルールを変更する。
変更するには、以下のようなプロンプトを追加する。

プロンプト
- "リリース日" と "BPM" は integer として扱いたい

完成

再生成されたコードを以下に貼付する。

実行してみると、エラーなく処理が完了した。
想定通り動作しているように見える。

% python json_validator_adjust.py data.zip
% 
実行結果
% python json_validator_adjust.py data_invalid.zip
data_invalid.zip/1990/犬.json [deque([])]: 'period' is a required property

Failed validating 'required' in schema:
    {'$schema': 'http://json-schema.org/schema#',
     'properties': {'artist': {'type': 'string'},
                    'period': {'type': 'string'},
                    'trackList': {'items': {'properties': {'bpm': {'type': 'integer'},
                                                           'date': {'type': 'integer'},
                                                           'name': {'type': 'string'}},
                                            'required': ['name',
                                                         'date',
                                                         'bpm'],
                                            'type': 'object'},
                                  'type': 'array'}},
     'required': ['period', 'artist', 'trackList'],
     'type': 'object'}

On instance:
    {'artist': '犬',
     'trackList': [{'bpm': 80, 'date': 19940401, 'name': '遠吠えA'},
                   {'bpm': 60, 'date': 19991215, 'name': '遠吠えB'}]}
data_invalid.zip/1990/猫.json: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
data_invalid.zip/2000/鴨.json [deque([])]: 'artist' is a required property

Failed validating 'required' in schema:
    {'$schema': 'http://json-schema.org/schema#',
     'properties': {'artist': {'type': 'string'},
                    'period': {'type': 'string'},
                    'trackList': {'items': {'properties': {'bpm': {'type': 'integer'},
                                                           'date': {'type': 'integer'},
                                                           'name': {'type': 'string'}},
                                            'required': ['name',
                                                         'date',
                                                         'bpm'],
                                            'type': 'object'},
                                  'type': 'array'}},
     'required': ['period', 'artist', 'trackList'],
     'type': 'object'}

On instance:
    {'period': '2000',
     'trackList': [{'bpm': 145, 'date': 20061112, 'name': 'ピルピル'}]}
data_invalid.zip/2010/猿.json [deque(['trackList', 0, 'name'])]: False is not of type 'string'

Failed validating 'type' in schema['properties']['trackList']['items']['properties']['name']:
    {'type': 'string'}

On instance['trackList'][0]['name']:
    False
対象ファイル エラー内容
data_invalid.zip/1990/犬.json "period" 値が存在しない
data_invalid.zip/1990/猫.json ダブルクォーテーション不足によるシンタックスエラー
data_invalid.zip/2000/鴨.json "artist" 値が存在しない
data_invalid.zip/2010/猿.json "name" 値が文字列ではない

それぞれ仕込んだとおりのエラーになっているため、想定した動作になっているようだ。

GitHubで編集を提案

Discussion