📄
python の yaml.dump 面白すぎだろww
※ 情報量の少ないタイトルは釣りです。
何が起きたのか?
以前 FastAPI の openapi.json を yaml に変換する記事を書きました
が、面白いバグが発生しました。
日本の都道府県に都道府県コードと呼ばれる2桁のコードが割り振られています。
これをAPIでやり取りする際に、以下のような enum を定義して openapi.yaml を出力しました。
class PrefCode(str, CustomSchemaEnum):
HOKKAIDO = "01"
AOMORI = "02"
IWATE = "03"
MIYAGI = "04"
AKITA = "05"
YAMAGATA = "06"
FUKUSHIMA = "07"
IBARAKI = "08"
TOCHIGI = "09"
GUNMA = "10"
SAITAMA = "11"
# ...以下省略...
すると openapi.yaml では以下のような出力になりました。
PrefCode:
enum:
- '01'
- '02'
- '03'
- '04'
- '05'
- '06'
- '07'
- 08
- 09
- '10'
- '11'
# ...以下省略...
08 と 09 だけクォーテーションがないんですよね。この openapi.yaml でクライアントのコードを生成すると 08 と 09 が数値扱いになりました。
なぜ起きたのか
以下のコメントによると
0 から始まることは 8 進数であることを意味し、'06' や '07' はクォーテーションをつけないと 8 進数の数値なのか文字列なのか区別できないので '' をつける必要があるが、08 や 09 は無くても区別できるので、YAML 1.1 の仕様では '' をつけない。
ということらしいです。しかし YAML 1.2 では 08 や 09 にも '' を付けられるようになったようです。
解決方法
yamlcore というモジュールが公開されています。これを使えば解決します。
import yaml
from yamlcore import CoreDumper
openapi_yaml = yaml.dump(openapi_json, Dumper=CoreDumper)
PrefCode:
enum:
- '01'
- '02'
- '03'
- '04'
- '05'
- '06'
- '07'
- '08'
- '09'
- '10'
- '11'
# ...以下省略...
Discussion