Python · dict · nested JSON

遞迴將 Python dict keys 轉為 camelCase

巢狀 dict/list 不是單一字串 helper 能解決的問題;在 data boundary 遞迴轉換,collision 時直接失敗。

作者 Camel Case Converter 編輯團隊發布於 2026年9月12日最後審閱

遞迴轉換 dict 與 list key

from typing import Any

def snake_to_camel(name: str) -> str:
    parts = [part for part in name.split("_") if part]
    if not parts: return name
    head, *tail = parts
    return head.lower() + "".join(part[:1].upper() + part[1:].lower() for part in tail)

def keys_to_camel(value: Any) -> Any:
    if isinstance(value, list): return [keys_to_camel(item) for item in value]
    if not isinstance(value, dict): return value
    output: dict[Any, Any] = {}
    for key, child in value.items():
        next_key = snake_to_camel(key) if isinstance(key, str) else key
        if next_key in output: raise ValueError(f"Key collision: {next_key}")
        output[next_key] = keys_to_camel(child)
    return output

先處理 list,scalar 原樣回傳,dict 以 camelCase string key 重建。

JSON parse 後使用 converter

import json
snake_payload = json.loads(raw_json)
camel_payload = keys_to_camel(snake_payload)
print(json.dumps(camel_payload, indent=2))

json.loads 會產生一般 dict/list,因此 parse 後是一個清楚且可測試的 naming boundary。

需要時保留 underscore / dollar prefix

def snake_to_camel_preserving_prefix(name: str) -> str:
    prefix_length = len(name) - len(name.lstrip("_$"))
    prefix = name[:prefix_length]
    body = name[prefix_length:]
    return prefix + snake_to_camel(body)

遇到 _id、__typename、$schema_version,可先分離 prefix 再轉換剩餘名稱。

正式環境注意事項

  • 先決定重複 underscore 與空 token 要正規化還是保留。
  • user_id / userId collision 應拋出錯誤。
  • 只需轉換部分 payload 時使用排除鍵或 stop path。
  • dataclass、ORM、model、serializer 可能是更適合的 naming boundary。

線上測試 JSON 邊界

在實作前測試巢狀物件、陣列、排除鍵、stop paths、語意前綴、衝突與 key-only diff。

拖放 .json 檔案,或從裝置選取

檔案只會在瀏覽器中讀取。最大檔案大小:5 MB。

轉換後 JSON
{
  "userProfile": {
    "firstName": "Ada",
    "createdAt": "2026-09-12"
  }
}

解析、檔案讀取、格式化與鍵名轉換都在瀏覽器本機執行。JSON 不會傳送到轉換伺服器。