Python · dict · nested JSON
Convert Python dict keys to camelCase recursively
A string helper is not enough for nested dictionaries and lists. Convert keys recursively at the data boundary, preserve values, and fail on collisions.
Recursively convert dict and list keys
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 outputHandle lists before dictionaries, return scalar values unchanged, and rebuild each dict with converted string keys.
Use the converter after parsing JSON
import json
snake_payload = json.loads(raw_json)
camel_payload = keys_to_camel(snake_payload)
print(json.dumps(camel_payload, indent=2))json.loads produces ordinary dict and list structures, making the naming boundary easy to locate and test.
Preserve semantic underscore or dollar prefixes when needed
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)For keys such as _id, __typename, or $schema_version, separate meaningful prefixes before converting the remaining identifier.
Production considerations
- Decide whether repeated underscores and empty tokens should be normalized or preserved.
- A collision such as user_id and userId becoming one output key should raise an error.
- Use excluded keys or stop paths when only part of a payload belongs to the naming convention.
- Custom classes, dataclasses, ORM models, and serializers may provide a better boundary than recursive dict conversion.
Test the JSON boundary online
Use the browser tool to test nested objects, arrays, excluded keys, stop paths, semantic prefixes, collision handling, and a key-only diff before you copy the same convention into an application.
Drop a .json file here or choose one from your device
Files are read only in your browser. Maximum file size: 5 MB.
{
"userProfile": {
"firstName": "Ada",
"createdAt": "2026-09-12"
}
}Parsing, file reading, formatting, and key conversion run locally in your browser. JSON input is not sent to a conversion server.