dictknifeにshrinkコマンドを追加した
発端
qiitaのAPIを実行してみるとあるユーザーのストックの情報が取れるらしい(実はストックは公開情報だったんですね)。
GET /api/v2/users/:user_id/stocks
指定されたユーザがストックした記事一覧を、ストックした日時の降順で返します。
そしてここに含まれている以下のfieldが本文全文の値を保持している(一方はHTML化後)。
- rendered_body
- body
やばい。どのくらいやばいかというと、38MBとかになっている。
$ ls -lh src/stocks.yaml -rw-r--r-- 1 podhmo staff 38M 3 26 03:07 src/stocks.yaml
shrink
とりあえず小さくしたかったのでshrinkコマンドを追加した(まだpypiにはあげていない)。
$ dictknife shrink -h usage: dictknife shrink [-h] [--max-length-of-string MAX_LENGTH_OF_STRING] [--max-length-of-list MAX_LENGTH_OF_LIST] [--cont-suffix CONT_SUFFIX] [--with-tail] [-i {yaml,json,toml,csv,tsv,raw,env,md,markdown,spreadsheet}] [-o {yaml,json,toml,csv,tsv,raw,env,md,markdown,spreadsheet}] [files [files ...]] shrink positional arguments: files optional arguments: -h, --help show this help message and exit --max-length-of-string MAX_LENGTH_OF_STRING --max-length-of-list MAX_LENGTH_OF_LIST --cont-suffix CONT_SUFFIX --with-tail -i {yaml,json,toml,csv,tsv,raw,env,md,markdown,spreadsheet}, --input-format {yaml,json,toml,csv,tsv,raw,env,md,markdown,spreadsheet} -o {yaml,json,toml,csv,tsv,raw,env,md,markdown,spreadsheet}, --output-format {yaml,json,toml,csv,tsv,raw,env,md,markdown,spreadsheet}
shrinkを使って小さくする
defaultでは以下の様な仕様で捨てられる
- 文字列は100文字以上が切り捨てられる
- 配列は長さ3以上が切り捨てられる(先頭3件のみ取得)
それぞれ --max-length-of-string
, --max-length-of-list
で変更できる。
実際に使ってみると、38MBから17KBになったので小さくなった。
$ dictknife shrink src/stocks.yaml > /tmp/shrinked.yaml $ ls -lh /tmp/shrinked.yaml -rw-r--r-- 1 podhmo wheel 17K 4 1 15:49 /tmp/shrinked.yaml
shapeで比較
dictknife shapeでどういうkeyが存在するかを調べられる。
元のデータと比較してどのようなkeyが存在するかを比較して、JSONSchemaやOpenAPI docをなどを作ろうとしたときのために、fieldが欠損していないかなどを調べてみる。
$ diff -u <(dictknife shape src/stocks.yaml) <(dictknife shape /tmp/shrinked.yaml) --- /dev/fd/63 2020-04-01 15:53:17.000000000 +0900 +++ /dev/fd/62 2020-04-01 15:53:17.000000000 +0900 @@ -62,4 +62,3 @@ []/response/content/[]/user/website_url []/response/status_code []/response/url -?[]/response/content/[]/tags/[]/versions/[]
tagsが消えてしまっていた。まぁ先頭N件に含まれない場合には仕方がない。こうなってしまう。
--with-tail
で先頭と末尾N件取得するように変えられる。
$ diff -u <(dictknife shape src/stocks.yaml) <(dictknife shape <(dictknife shrink --with-tail src/stocks.yaml))
ちなみにdictknife shapeはこういう感じの出力だった(request,responseを余分に保持している。実際のresponseはresponseのcontent部分)。
$ dictknife shape /tmp/shrinked.yaml [] []/headers []/headers/Cache-Control []/headers/Connection []/headers/Content-Type []/headers/Date []/headers/ETag []/headers/Link []/headers/Rate-Limit []/headers/Rate-Remaining []/headers/Rate-Reset []/headers/Referrer-Policy []/headers/Server []/headers/Strict-Transport-Security []/headers/Total-Count []/headers/Transfer-Encoding []/headers/Vary []/headers/X-Content-Type-Options []/headers/X-Download-Options []/headers/X-Frame-Options []/headers/X-Permitted-Cross-Domain-Policies []/headers/X-Request-Id []/headers/X-Runtime []/headers/X-XSS-Protection []/response []/response/content []/response/content/[] []/response/content/[]/body []/response/content/[]/coediting []/response/content/[]/comments_count []/response/content/[]/created_at []/response/content/[]/group []/response/content/[]/id []/response/content/[]/likes_count []/response/content/[]/page_views_count []/response/content/[]/private []/response/content/[]/reactions_count []/response/content/[]/rendered_body []/response/content/[]/tags []/response/content/[]/tags/[] []/response/content/[]/tags/[]/name []/response/content/[]/tags/[]/versions []/response/content/[]/title []/response/content/[]/updated_at []/response/content/[]/url []/response/content/[]/user []/response/content/[]/user/description []/response/content/[]/user/facebook_id []/response/content/[]/user/followees_count []/response/content/[]/user/followers_count []/response/content/[]/user/github_login_name []/response/content/[]/user/id []/response/content/[]/user/items_count []/response/content/[]/user/linkedin_id []/response/content/[]/user/location []/response/content/[]/user/name []/response/content/[]/user/organization []/response/content/[]/user/permanent_id []/response/content/[]/user/profile_image_url []/response/content/[]/user/team_only []/response/content/[]/user/twitter_screen_name []/response/content/[]/user/website_url []/response/status_code []/response/url
shrink後のyamlはこのようなもの