# api-json-cleaner
APIレスポンス由来の「汚いJSON」をキレイに整えて、安全にパース・保存するためのPythonライブラリです。日本語の文字化けや、二重エスケープ、未クォートキー、末尾カンマ、ベンダー独自フォーマットなど、実務で遭遇しがちな“微妙に壊れたJSON”を可能な範囲で自動修復します。
## 特徴
- 文字コード自動判定(charset-normalizer)で日本語の文字化けを低減/BOM除去/制御文字の除去
- API特有の二重エスケープやHTMLエンティティ残骸を正規化(パース後の値に限定)
- 未クォートキーや末尾カンマなどの軽症を安全に修復
- 日本語特化の正規化(既定ON)
- Unicode正規化(NFKC/NFC)、改行統一(CRLF/CR→LF)
- 波ダッシュ(〜)の字形統一、カナ文脈のダッシュ→長音符(ー)
- 円記号/バックスラッシュの相互変換(オプション)、軽度の文字化け補修(ftfy・任意)
- JSON5風の記法(コメント/単一引用符/末尾カンマなど)をフォールバックで許容(既定ON)
- 代表的なベンダー癖に対応(基本は安全側。必要に応じて有効化)
- anti-JSON-hijacking “)]}',” の除去
- `for(;;);` / `while(1);` の除去
- 長さプレフィックス `123\n{...}` の除去
- JSONP `callbackName({...});` の中身抽出
- NDJSON(1行1JSON)を配列へフォールバック解釈
- トップレベルラップ解除(results/items/data/payload/d)・内部JSON文字列の再パース(既定OFF)
- Pythonオブジェクトで返却/任意でJSON保存
- CLI同梱(`apijsonclean`)
## インストール
```
pip install .
```
Python 3.9+ が必要です。文字化け補修を強めたい場合は任意で `ftfy` の導入も可能です。
## 使い方(Python)
```python
from api_json_cleaner import cleanse_and_parse, save_json
from api_json_cleaner.cleaner import CleanOptions
raw = b'\xef\xbb\xbf{"message":"Hello,\n\"world\"","data":[1,2,3,], unquoted_key: 1}'
opts = CleanOptions( # 必要に応じて調整
allow_json5=True,
ja_mode=True,
yen_backslash="preserve", # "yen-to-backslash" や "backslash-to-yen" も可
)
obj = cleanse_and_parse(raw, options=opts)
print(obj)
# {'message': 'Hello,\n"world"', 'data': [1, 2, 3], 'unquoted_key': 1}
save_json(obj, 'out.json', ensure_ascii=False, indent=2)
```
## 使い方(CLI)
- 標準入力から受け取り整形だけ出力(パースなし)
```
apijsonclean --raw < dirty.json > cleaned.json
```
- パースして整形保存(日本語を非エスケープで保存)
```
apijsonclean dirty.json -o cleaned.json --no-ascii
```
- JSON5フォールバックを無効化(厳密モード)
```
apijsonclean dirty.json --no-json5
```
## API
- `clean_json_text(data: bytes | str, options: CleanOptions | None = None) -> str`
- JSON文字列のクレンジングのみ(構文は検証しません)。
- `parse(data: bytes | str, options: CleanOptions | None = None) -> Any`
- クレンジング後に厳密JSON→再試行→JSON5/NDJSONの順でパース。
- `save_json(obj: Any, path: str, ensure_ascii: bool = True, indent: int = 2)`
- PythonデータをJSONで保存。
- `cleanse_and_parse(data: bytes | str, save_to: str | None = None, options: CleanOptions | None = None) -> Any`
- まとめてクレンジング→パース→(任意で保存)。
### 主な`CleanOptions`(抜粋)
- 日本語: `ja_mode`, `unicode_normalization`, `normalize_newlines`, `unify_wave_tilde`, `unify_prolonged_sound_mark`, `unify_hyphen`, `yen_backslash`, `fix_mojibake`
- JSON5/拡張: `allow_json5`
- ベンダー癖: `allow_jsonp`, `allow_js_prefix`, `allow_length_prefix`, `allow_ndjson`, `unwrap_singleton_container`(既定OFF), `prefer_primary_container`(既定OFF), `parse_inner_json_strings`(既定OFF), `inner_json_max_size`
### JSON5互換について
`CleanOptions(allow_json5=True)` が既定で有効です。厳密なJSONとしての読み込みが失敗した場合に `json5` でのフォールバックを試みます(コメントや単一引用符、末尾カンマを扱えます)。厳密モードを望む場合は `allow_json5=False` または CLI で `--no-json5` を指定してください。
## ベンダー固有フォーマット例
- JSONP: `callbackName({"a":1, unq:2,})` → `{ "a": 1, "unq": 2 }`
- NDJSON: `{"id":1}\n{"id":2}\n...` → `[{"id":1},{"id":2},...]`
- anti-JSON-hijacking: `)]}',\n{...}` → `{...}`
- `for(;;); { ... }` / `while(1); { ... }` → `{ ... }`
- `123\n{...}`(長さプレフィックス) → `{...}`
- `{"results":[...]}` や `{"data":{...}}` を本体へ展開
- 値がJSON文字列なら安全に再パース(サイズ/深さ制限あり)
## テスト
本リポジトリにはPytestが含まれます。
```
python -m pytest -q -k "not slow" # 機能テスト
python -m pytest -q # すべて(slow含む)
```
## 注意
- 本ライブラリは「完全に壊れたJSON」を魔法のように修復できるわけではありません。安全に推測可能な範囲のみ修正します。
- 未クォートキーの修正は一般的な英数字とアンダースコア・ハイフンのみを対象としています。
- JSON5/NDJSON/ベンダー癖対応はフォールバックで行うため、状況により無効化して厳密運用を推奨します。
## ライセンス
MIT
Raw data
{
"_id": null,
"home_page": null,
"name": "api-json-cleaner",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.9",
"maintainer_email": null,
"keywords": "json, api, clean, sanitize, mojibake, encoding, japanese",
"author": null,
"author_email": "Your Name <you@example.com>",
"download_url": "https://files.pythonhosted.org/packages/20/ec/cbc9c70496b8180f9900cc1754956ee7b2786f7160a57e9cb83bc314eb0e/api_json_cleaner-0.1.0.1.tar.gz",
"platform": null,
"description": "# api-json-cleaner\r\n\r\nAPI\u30ec\u30b9\u30dd\u30f3\u30b9\u7531\u6765\u306e\u300c\u6c5a\u3044JSON\u300d\u3092\u30ad\u30ec\u30a4\u306b\u6574\u3048\u3066\u3001\u5b89\u5168\u306b\u30d1\u30fc\u30b9\u30fb\u4fdd\u5b58\u3059\u308b\u305f\u3081\u306ePython\u30e9\u30a4\u30d6\u30e9\u30ea\u3067\u3059\u3002\u65e5\u672c\u8a9e\u306e\u6587\u5b57\u5316\u3051\u3084\u3001\u4e8c\u91cd\u30a8\u30b9\u30b1\u30fc\u30d7\u3001\u672a\u30af\u30a9\u30fc\u30c8\u30ad\u30fc\u3001\u672b\u5c3e\u30ab\u30f3\u30de\u3001\u30d9\u30f3\u30c0\u30fc\u72ec\u81ea\u30d5\u30a9\u30fc\u30de\u30c3\u30c8\u306a\u3069\u3001\u5b9f\u52d9\u3067\u906d\u9047\u3057\u304c\u3061\u306a\u201c\u5fae\u5999\u306b\u58ca\u308c\u305fJSON\u201d\u3092\u53ef\u80fd\u306a\u7bc4\u56f2\u3067\u81ea\u52d5\u4fee\u5fa9\u3057\u307e\u3059\u3002\r\n\r\n## \u7279\u5fb4\r\n- \u6587\u5b57\u30b3\u30fc\u30c9\u81ea\u52d5\u5224\u5b9a\uff08charset-normalizer\uff09\u3067\u65e5\u672c\u8a9e\u306e\u6587\u5b57\u5316\u3051\u3092\u4f4e\u6e1b\uff0fBOM\u9664\u53bb\uff0f\u5236\u5fa1\u6587\u5b57\u306e\u9664\u53bb\r\n- API\u7279\u6709\u306e\u4e8c\u91cd\u30a8\u30b9\u30b1\u30fc\u30d7\u3084HTML\u30a8\u30f3\u30c6\u30a3\u30c6\u30a3\u6b8b\u9ab8\u3092\u6b63\u898f\u5316\uff08\u30d1\u30fc\u30b9\u5f8c\u306e\u5024\u306b\u9650\u5b9a\uff09\r\n- \u672a\u30af\u30a9\u30fc\u30c8\u30ad\u30fc\u3084\u672b\u5c3e\u30ab\u30f3\u30de\u306a\u3069\u306e\u8efd\u75c7\u3092\u5b89\u5168\u306b\u4fee\u5fa9\r\n- \u65e5\u672c\u8a9e\u7279\u5316\u306e\u6b63\u898f\u5316\uff08\u65e2\u5b9aON\uff09\r\n - Unicode\u6b63\u898f\u5316\uff08NFKC/NFC\uff09\u3001\u6539\u884c\u7d71\u4e00\uff08CRLF/CR\u2192LF\uff09\r\n - \u6ce2\u30c0\u30c3\u30b7\u30e5\uff08\u301c\uff09\u306e\u5b57\u5f62\u7d71\u4e00\u3001\u30ab\u30ca\u6587\u8108\u306e\u30c0\u30c3\u30b7\u30e5\u2192\u9577\u97f3\u7b26\uff08\u30fc\uff09\r\n - \u5186\u8a18\u53f7/\u30d0\u30c3\u30af\u30b9\u30e9\u30c3\u30b7\u30e5\u306e\u76f8\u4e92\u5909\u63db\uff08\u30aa\u30d7\u30b7\u30e7\u30f3\uff09\u3001\u8efd\u5ea6\u306e\u6587\u5b57\u5316\u3051\u88dc\u4fee\uff08ftfy\u30fb\u4efb\u610f\uff09\r\n- JSON5\u98a8\u306e\u8a18\u6cd5\uff08\u30b3\u30e1\u30f3\u30c8/\u5358\u4e00\u5f15\u7528\u7b26/\u672b\u5c3e\u30ab\u30f3\u30de\u306a\u3069\uff09\u3092\u30d5\u30a9\u30fc\u30eb\u30d0\u30c3\u30af\u3067\u8a31\u5bb9\uff08\u65e2\u5b9aON\uff09\r\n- \u4ee3\u8868\u7684\u306a\u30d9\u30f3\u30c0\u30fc\u7656\u306b\u5bfe\u5fdc\uff08\u57fa\u672c\u306f\u5b89\u5168\u5074\u3002\u5fc5\u8981\u306b\u5fdc\u3058\u3066\u6709\u52b9\u5316\uff09\r\n - anti-JSON-hijacking \u201c)]}',\u201d \u306e\u9664\u53bb\r\n - `for(;;);` / `while(1);` \u306e\u9664\u53bb\r\n - \u9577\u3055\u30d7\u30ec\u30d5\u30a3\u30c3\u30af\u30b9 `123\\n{...}` \u306e\u9664\u53bb\r\n - JSONP `callbackName({...});` \u306e\u4e2d\u8eab\u62bd\u51fa\r\n - NDJSON\uff081\u884c1JSON\uff09\u3092\u914d\u5217\u3078\u30d5\u30a9\u30fc\u30eb\u30d0\u30c3\u30af\u89e3\u91c8\r\n - \u30c8\u30c3\u30d7\u30ec\u30d9\u30eb\u30e9\u30c3\u30d7\u89e3\u9664\uff08results/items/data/payload/d\uff09\u30fb\u5185\u90e8JSON\u6587\u5b57\u5217\u306e\u518d\u30d1\u30fc\u30b9\uff08\u65e2\u5b9aOFF\uff09\r\n- Python\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3067\u8fd4\u5374\uff0f\u4efb\u610f\u3067JSON\u4fdd\u5b58\r\n- CLI\u540c\u68b1\uff08`apijsonclean`\uff09\r\n\r\n## \u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\r\n```\r\npip install .\r\n```\r\nPython 3.9+ \u304c\u5fc5\u8981\u3067\u3059\u3002\u6587\u5b57\u5316\u3051\u88dc\u4fee\u3092\u5f37\u3081\u305f\u3044\u5834\u5408\u306f\u4efb\u610f\u3067 `ftfy` \u306e\u5c0e\u5165\u3082\u53ef\u80fd\u3067\u3059\u3002\r\n\r\n## \u4f7f\u3044\u65b9\uff08Python\uff09\r\n```python\r\nfrom api_json_cleaner import cleanse_and_parse, save_json\r\nfrom api_json_cleaner.cleaner import CleanOptions\r\n\r\nraw = b'\\xef\\xbb\\xbf{\"message\":\"Hello,\\n\\\"world\\\"\",\"data\":[1,2,3,], unquoted_key: 1}'\r\nopts = CleanOptions( # \u5fc5\u8981\u306b\u5fdc\u3058\u3066\u8abf\u6574\r\n allow_json5=True,\r\n ja_mode=True,\r\n yen_backslash=\"preserve\", # \"yen-to-backslash\" \u3084 \"backslash-to-yen\" \u3082\u53ef\r\n)\r\nobj = cleanse_and_parse(raw, options=opts)\r\nprint(obj)\r\n# {'message': 'Hello,\\n\"world\"', 'data': [1, 2, 3], 'unquoted_key': 1}\r\n\r\nsave_json(obj, 'out.json', ensure_ascii=False, indent=2)\r\n```\r\n\r\n## \u4f7f\u3044\u65b9\uff08CLI\uff09\r\n- \u6a19\u6e96\u5165\u529b\u304b\u3089\u53d7\u3051\u53d6\u308a\u6574\u5f62\u3060\u3051\u51fa\u529b\uff08\u30d1\u30fc\u30b9\u306a\u3057\uff09\r\n```\r\napijsonclean --raw < dirty.json > cleaned.json\r\n```\r\n- \u30d1\u30fc\u30b9\u3057\u3066\u6574\u5f62\u4fdd\u5b58\uff08\u65e5\u672c\u8a9e\u3092\u975e\u30a8\u30b9\u30b1\u30fc\u30d7\u3067\u4fdd\u5b58\uff09\r\n```\r\napijsonclean dirty.json -o cleaned.json --no-ascii\r\n```\r\n- JSON5\u30d5\u30a9\u30fc\u30eb\u30d0\u30c3\u30af\u3092\u7121\u52b9\u5316\uff08\u53b3\u5bc6\u30e2\u30fc\u30c9\uff09\r\n```\r\napijsonclean dirty.json --no-json5\r\n```\r\n\r\n## API\r\n- `clean_json_text(data: bytes | str, options: CleanOptions | None = None) -> str`\r\n - JSON\u6587\u5b57\u5217\u306e\u30af\u30ec\u30f3\u30b8\u30f3\u30b0\u306e\u307f\uff08\u69cb\u6587\u306f\u691c\u8a3c\u3057\u307e\u305b\u3093\uff09\u3002\r\n- `parse(data: bytes | str, options: CleanOptions | None = None) -> Any`\r\n - \u30af\u30ec\u30f3\u30b8\u30f3\u30b0\u5f8c\u306b\u53b3\u5bc6JSON\u2192\u518d\u8a66\u884c\u2192JSON5/NDJSON\u306e\u9806\u3067\u30d1\u30fc\u30b9\u3002\r\n- `save_json(obj: Any, path: str, ensure_ascii: bool = True, indent: int = 2)`\r\n - Python\u30c7\u30fc\u30bf\u3092JSON\u3067\u4fdd\u5b58\u3002\r\n- `cleanse_and_parse(data: bytes | str, save_to: str | None = None, options: CleanOptions | None = None) -> Any`\r\n - \u307e\u3068\u3081\u3066\u30af\u30ec\u30f3\u30b8\u30f3\u30b0\u2192\u30d1\u30fc\u30b9\u2192\uff08\u4efb\u610f\u3067\u4fdd\u5b58\uff09\u3002\r\n\r\n### \u4e3b\u306a`CleanOptions`\uff08\u629c\u7c8b\uff09\r\n- \u65e5\u672c\u8a9e: `ja_mode`, `unicode_normalization`, `normalize_newlines`, `unify_wave_tilde`, `unify_prolonged_sound_mark`, `unify_hyphen`, `yen_backslash`, `fix_mojibake`\r\n- JSON5/\u62e1\u5f35: `allow_json5`\r\n- \u30d9\u30f3\u30c0\u30fc\u7656: `allow_jsonp`, `allow_js_prefix`, `allow_length_prefix`, `allow_ndjson`, `unwrap_singleton_container`(\u65e2\u5b9aOFF), `prefer_primary_container`(\u65e2\u5b9aOFF), `parse_inner_json_strings`(\u65e2\u5b9aOFF), `inner_json_max_size`\r\n\r\n### JSON5\u4e92\u63db\u306b\u3064\u3044\u3066\r\n`CleanOptions(allow_json5=True)` \u304c\u65e2\u5b9a\u3067\u6709\u52b9\u3067\u3059\u3002\u53b3\u5bc6\u306aJSON\u3068\u3057\u3066\u306e\u8aad\u307f\u8fbc\u307f\u304c\u5931\u6557\u3057\u305f\u5834\u5408\u306b `json5` \u3067\u306e\u30d5\u30a9\u30fc\u30eb\u30d0\u30c3\u30af\u3092\u8a66\u307f\u307e\u3059\uff08\u30b3\u30e1\u30f3\u30c8\u3084\u5358\u4e00\u5f15\u7528\u7b26\u3001\u672b\u5c3e\u30ab\u30f3\u30de\u3092\u6271\u3048\u307e\u3059\uff09\u3002\u53b3\u5bc6\u30e2\u30fc\u30c9\u3092\u671b\u3080\u5834\u5408\u306f `allow_json5=False` \u307e\u305f\u306f CLI \u3067 `--no-json5` \u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002\r\n\r\n## \u30d9\u30f3\u30c0\u30fc\u56fa\u6709\u30d5\u30a9\u30fc\u30de\u30c3\u30c8\u4f8b\r\n- JSONP: `callbackName({\"a\":1, unq:2,})` \u2192 `{ \"a\": 1, \"unq\": 2 }`\r\n- NDJSON: `{\"id\":1}\\n{\"id\":2}\\n...` \u2192 `[{\"id\":1},{\"id\":2},...]`\r\n- anti-JSON-hijacking: `)]}',\\n{...}` \u2192 `{...}`\r\n- `for(;;); { ... }` / `while(1); { ... }` \u2192 `{ ... }`\r\n- `123\\n{...}`\uff08\u9577\u3055\u30d7\u30ec\u30d5\u30a3\u30c3\u30af\u30b9\uff09 \u2192 `{...}`\r\n- `{\"results\":[...]}` \u3084 `{\"data\":{...}}` \u3092\u672c\u4f53\u3078\u5c55\u958b\r\n- \u5024\u304cJSON\u6587\u5b57\u5217\u306a\u3089\u5b89\u5168\u306b\u518d\u30d1\u30fc\u30b9\uff08\u30b5\u30a4\u30ba/\u6df1\u3055\u5236\u9650\u3042\u308a\uff09\r\n\r\n## \u30c6\u30b9\u30c8\r\n\u672c\u30ea\u30dd\u30b8\u30c8\u30ea\u306b\u306fPytest\u304c\u542b\u307e\u308c\u307e\u3059\u3002\r\n```\r\npython -m pytest -q -k \"not slow\" # \u6a5f\u80fd\u30c6\u30b9\u30c8\r\npython -m pytest -q # \u3059\u3079\u3066\uff08slow\u542b\u3080\uff09\r\n```\r\n\r\n## \u6ce8\u610f\r\n- \u672c\u30e9\u30a4\u30d6\u30e9\u30ea\u306f\u300c\u5b8c\u5168\u306b\u58ca\u308c\u305fJSON\u300d\u3092\u9b54\u6cd5\u306e\u3088\u3046\u306b\u4fee\u5fa9\u3067\u304d\u308b\u308f\u3051\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002\u5b89\u5168\u306b\u63a8\u6e2c\u53ef\u80fd\u306a\u7bc4\u56f2\u306e\u307f\u4fee\u6b63\u3057\u307e\u3059\u3002\r\n- \u672a\u30af\u30a9\u30fc\u30c8\u30ad\u30fc\u306e\u4fee\u6b63\u306f\u4e00\u822c\u7684\u306a\u82f1\u6570\u5b57\u3068\u30a2\u30f3\u30c0\u30fc\u30b9\u30b3\u30a2\u30fb\u30cf\u30a4\u30d5\u30f3\u306e\u307f\u3092\u5bfe\u8c61\u3068\u3057\u3066\u3044\u307e\u3059\u3002\r\n- JSON5/NDJSON/\u30d9\u30f3\u30c0\u30fc\u7656\u5bfe\u5fdc\u306f\u30d5\u30a9\u30fc\u30eb\u30d0\u30c3\u30af\u3067\u884c\u3046\u305f\u3081\u3001\u72b6\u6cc1\u306b\u3088\u308a\u7121\u52b9\u5316\u3057\u3066\u53b3\u5bc6\u904b\u7528\u3092\u63a8\u5968\u3057\u307e\u3059\u3002\r\n\r\n## \u30e9\u30a4\u30bb\u30f3\u30b9\r\nMIT\r\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "API\u30ec\u30b9\u30dd\u30f3\u30b9\u306e\"\u6c5a\u3044\"JSON\u3092\u30ad\u30ec\u30a4\u306b\u3057\u3066\u5b89\u5168\u306b\u30d1\u30fc\u30b9\u30fb\u4fdd\u5b58\u3059\u308b\u305f\u3081\u306ePython\u30e9\u30a4\u30d6\u30e9\u30ea",
"version": "0.1.0.1",
"project_urls": {
"Homepage": "https://github.com/hayashikunita/api-json-cleaner",
"Issues": "https://github.com/hayashikunita/api-json-cleaner/issues",
"Repository": "https://github.com/hayashikunita/api-json-cleaner"
},
"split_keywords": [
"json",
" api",
" clean",
" sanitize",
" mojibake",
" encoding",
" japanese"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "480d453a3a217b381e4a85960ccb5f0729d85ffa43bc8b5dd4656b3bf7615a1b",
"md5": "4867d32b011edc5becb486b2384d1474",
"sha256": "8e747063091a0850bb6f9f3fa1ecf5c38af2bef2f086d0308ac9c92dbbf7a8b4"
},
"downloads": -1,
"filename": "api_json_cleaner-0.1.0.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "4867d32b011edc5becb486b2384d1474",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.9",
"size": 12003,
"upload_time": "2025-08-30T16:38:04",
"upload_time_iso_8601": "2025-08-30T16:38:04.591532Z",
"url": "https://files.pythonhosted.org/packages/48/0d/453a3a217b381e4a85960ccb5f0729d85ffa43bc8b5dd4656b3bf7615a1b/api_json_cleaner-0.1.0.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "20eccbc9c70496b8180f9900cc1754956ee7b2786f7160a57e9cb83bc314eb0e",
"md5": "ef5ead972ac58e653be27bd0c67bc1a0",
"sha256": "b3ec06d54162dff5b7e50855ff32c9a1e922f72a89699811630005f87e5ebcfa"
},
"downloads": -1,
"filename": "api_json_cleaner-0.1.0.1.tar.gz",
"has_sig": false,
"md5_digest": "ef5ead972ac58e653be27bd0c67bc1a0",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.9",
"size": 14390,
"upload_time": "2025-08-30T16:38:05",
"upload_time_iso_8601": "2025-08-30T16:38:05.549109Z",
"url": "https://files.pythonhosted.org/packages/20/ec/cbc9c70496b8180f9900cc1754956ee7b2786f7160a57e9cb83bc314eb0e/api_json_cleaner-0.1.0.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-08-30 16:38:05",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "hayashikunita",
"github_project": "api-json-cleaner",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "api-json-cleaner"
}