A comprehensive Python library for serializing and deserializing Python objects to and from JSON (dictionaries) with minimal code changes required.
81
Utilities for transforming dictionary keys between different naming conventions. The jsons library provides built-in functions to convert keys between camelCase, snake_case, PascalCase, and lisp-case formats, which is especially useful for API integration and cross-platform data exchange.
def camelcase(str_):
"""
Transform string to camelCase format.
Parameters:
- str_: String to be transformed
Returns:
str: String in camelCase format (first letter lowercase, subsequent words capitalized)
Examples:
- 'hello_world' -> 'helloWorld'
- 'user-name' -> 'userName'
- 'API_KEY' -> 'apiKey'
"""
def snakecase(str_):
"""
Transform string to snake_case format.
Parameters:
- str_: String to be transformed
Returns:
str: String in snake_case format (all lowercase with underscores)
Examples:
- 'helloWorld' -> 'hello_world'
- 'UserName' -> 'user_name'
- 'API-Key' -> 'api_key'
"""
def pascalcase(str_):
"""
Transform string to PascalCase format.
Parameters:
- str_: String to be transformed
Returns:
str: String in PascalCase format (first letter uppercase, subsequent words capitalized)
Examples:
- 'hello_world' -> 'HelloWorld'
- 'user-name' -> 'UserName'
- 'api_key' -> 'ApiKey'
"""
def lispcase(str_):
"""
Transform string to lisp-case format.
Parameters:
- str_: String to be transformed
Returns:
str: String in lisp-case format (all lowercase with hyphens)
Examples:
- 'helloWorld' -> 'hello-world'
- 'UserName' -> 'user-name'
- 'api_key' -> 'api-key'
"""# Pre-defined constants for use with dump/load functions
KEY_TRANSFORMER_SNAKECASE = snakecase
KEY_TRANSFORMER_CAMELCASE = camelcase
KEY_TRANSFORMER_PASCALCASE = pascalcase
KEY_TRANSFORMER_LISPCASE = lispcaseimport jsons
from jsons import camelcase, snakecase, pascalcase, lispcase
# Transform individual strings
original = "user_profile_data"
print(camelcase(original)) # 'userProfileData'
print(snakecase(original)) # 'user_profile_data' (no change)
print(pascalcase(original)) # 'UserProfileData'
print(lispcase(original)) # 'user-profile-data'
# Transform from camelCase
camel_string = "firstName"
print(snakecase(camel_string)) # 'first_name'
print(pascalcase(camel_string)) # 'FirstName'
print(lispcase(camel_string)) # 'first-name'
# Transform with hyphens and mixed formats
mixed_string = "API-Response-Data"
print(camelcase(mixed_string)) # 'apiResponseData'
print(snakecase(mixed_string)) # 'api_response_data'
print(pascalcase(mixed_string)) # 'ApiResponseData'import jsons
from jsons import KEY_TRANSFORMER_CAMELCASE, KEY_TRANSFORMER_SNAKECASE
from dataclasses import dataclass
@dataclass
class UserProfile:
first_name: str
last_name: str
email_address: str
phone_number: str
is_active: bool
user = UserProfile(
first_name="John",
last_name="Doe",
email_address="john.doe@example.com",
phone_number="+1-555-0100",
is_active=True
)
# Serialize with camelCase keys
camel_json = jsons.dump(user, key_transformer=KEY_TRANSFORMER_CAMELCASE)
print(camel_json)
# {
# 'firstName': 'John',
# 'lastName': 'Doe',
# 'emailAddress': 'john.doe@example.com',
# 'phoneNumber': '+1-555-0100',
# 'isActive': True
# }
# Serialize with snake_case keys (default, no transformation needed)
snake_json = jsons.dump(user)
print(snake_json)
# {
# 'first_name': 'John',
# 'last_name': 'Doe',
# 'email_address': 'john.doe@example.com',
# 'phone_number': '+1-555-0100',
# 'is_active': True
# }import jsons
from jsons import KEY_TRANSFORMER_SNAKECASE, KEY_TRANSFORMER_CAMELCASE
from dataclasses import dataclass
@dataclass
class APIResponse:
user_id: int
user_name: str
created_at: str
is_verified: bool
# Deserialize from camelCase JSON (common in JavaScript APIs)
camel_data = {
'userId': 12345,
'userName': 'alice_smith',
'createdAt': '2023-12-01T10:30:00Z',
'isVerified': True
}
# Transform camelCase keys to snake_case during deserialization
response = jsons.load(camel_data, APIResponse, key_transformer=KEY_TRANSFORMER_SNAKECASE)
print(response.user_id) # 12345
print(response.user_name) # 'alice_smith'
print(response.created_at) # '2023-12-01T10:30:00Z'
print(response.is_verified) # Trueimport jsons
from jsons import KEY_TRANSFORMER_CAMELCASE, KEY_TRANSFORMER_SNAKECASE
from dataclasses import dataclass
from typing import List
@dataclass
class ProductInfo:
product_id: int
product_name: str
unit_price: float
in_stock: bool
category_tags: List[str]
# Python uses snake_case internally
product = ProductInfo(
product_id=101,
product_name="Wireless Headphones",
unit_price=99.99,
in_stock=True,
category_tags=["electronics", "audio", "wireless"]
)
# Send to JavaScript API (requires camelCase)
api_payload = jsons.dump(product, key_transformer=KEY_TRANSFORMER_CAMELCASE)
print("Sending to API:")
print(api_payload)
# {
# 'productId': 101,
# 'productName': 'Wireless Headphones',
# 'unitPrice': 99.99,
# 'inStock': True,
# 'categoryTags': ['electronics', 'audio', 'wireless']
# }
# Receive from JavaScript API (camelCase format)
api_response = {
'productId': 102,
'productName': 'Bluetooth Speaker',
'unitPrice': 79.99,
'inStock': False,
'categoryTags': ['electronics', 'audio', 'bluetooth']
}
# Convert back to Python object with snake_case
received_product = jsons.load(api_response, ProductInfo, key_transformer=KEY_TRANSFORMER_SNAKECASE)
print("Received from API:")
print(f"Product: {received_product.product_name}")
print(f"Price: ${received_product.unit_price}")
print(f"Available: {received_product.in_stock}")import jsons
from jsons import JsonSerializable, KEY_TRANSFORMER_CAMELCASE, KEY_TRANSFORMER_SNAKECASE
# Create specialized classes for different API formats
JavaScriptAPI = JsonSerializable.with_dump(
key_transformer=KEY_TRANSFORMER_CAMELCASE
).with_load(
key_transformer=KEY_TRANSFORMER_SNAKECASE
)
class WebUser(JavaScriptAPI):
def __init__(self, user_id: int, full_name: str, email_address: str):
self.user_id = user_id
self.full_name = full_name
self.email_address = email_address
user = WebUser(123, "Jane Doe", "jane@example.com")
# Automatically uses camelCase for JSON output
user_json = user.json
print(user_json)
# {'userId': 123, 'fullName': 'Jane Doe', 'emailAddress': 'jane@example.com'}
# Automatically converts camelCase input to snake_case attributes
camel_input = {'userId': 456, 'fullName': 'Bob Smith', 'emailAddress': 'bob@example.com'}
new_user = WebUser.from_json(camel_input)
print(new_user.user_id) # 456
print(new_user.full_name) # 'Bob Smith'
print(new_user.email_address) # 'bob@example.com'import jsons
from jsons import KEY_TRANSFORMER_CAMELCASE, KEY_TRANSFORMER_SNAKECASE
from dataclasses import dataclass
from typing import Dict, List
@dataclass
class ContactInfo:
phone_number: str
email_address: str
home_address: str
@dataclass
class EmployeeRecord:
employee_id: int
first_name: str
last_name: str
contact_info: ContactInfo
skill_ratings: Dict[str, int]
project_history: List[str]
# Create complex nested object
employee = EmployeeRecord(
employee_id=1001,
first_name="Sarah",
last_name="Johnson",
contact_info=ContactInfo(
phone_number="555-0123",
email_address="sarah.j@company.com",
home_address="123 Oak Street"
),
skill_ratings={"python_programming": 9, "project_management": 8, "data_analysis": 7},
project_history=["web_redesign", "mobile_app", "data_migration"]
)
# Transform all nested keys to camelCase
camel_json = jsons.dump(employee, key_transformer=KEY_TRANSFORMER_CAMELCASE)
print(camel_json)
# {
# 'employeeId': 1001,
# 'firstName': 'Sarah',
# 'lastName': 'Johnson',
# 'contactInfo': {
# 'phoneNumber': '555-0123',
# 'emailAddress': 'sarah.j@company.com',
# 'homeAddress': '123 Oak Street'
# },
# 'skillRatings': {'pythonProgramming': 9, 'projectManagement': 8, 'dataAnalysis': 7},
# 'projectHistory': ['web_redesign', 'mobile_app', 'data_migration']
# }
# Deserialize camelCase back to snake_case structure
restored_employee = jsons.load(camel_json, EmployeeRecord, key_transformer=KEY_TRANSFORMER_SNAKECASE)
print(restored_employee.employee_id) # 1001
print(restored_employee.contact_info.phone_number) # '555-0123'
print(restored_employee.skill_ratings['python_programming']) # 9import jsons
from jsons import KEY_TRANSFORMER_PASCALCASE, KEY_TRANSFORMER_LISPCASE, KEY_TRANSFORMER_SNAKECASE
from dataclasses import dataclass
@dataclass
class ConfigData:
server_host: str
server_port: int
database_url: str
cache_timeout: int
debug_mode: bool
config = ConfigData(
server_host="localhost",
server_port=8080,
database_url="postgresql://localhost/mydb",
cache_timeout=300,
debug_mode=True
)
# Generate different formats for different systems
formats = {
"JavaScript API": jsons.dump(config, key_transformer=jsons.camelcase),
"C# API": jsons.dump(config, key_transformer=KEY_TRANSFORMER_PASCALCASE),
"Lisp/Clojure": jsons.dump(config, key_transformer=KEY_TRANSFORMER_LISPCASE),
"Python/Ruby": jsons.dump(config, key_transformer=KEY_TRANSFORMER_SNAKECASE)
}
for system, format_data in formats.items():
print(f"{system}:")
print(format_data)
print()
# Output:
# JavaScript API:
# {'serverHost': 'localhost', 'serverPort': 8080, 'databaseUrl': '...', 'cacheTimeout': 300, 'debugMode': True}
#
# C# API:
# {'ServerHost': 'localhost', 'ServerPort': 8080, 'DatabaseUrl': '...', 'CacheTimeout': 300, 'DebugMode': True}
#
# Lisp/Clojure:
# {'server-host': 'localhost', 'server-port': 8080, 'database-url': '...', 'cache-timeout': 300, 'debug-mode': True}
#
# Python/Ruby:
# {'server_host': 'localhost', 'server_port': 8080, 'database_url': '...', 'cache_timeout': 300, 'debug_mode': True}Install with Tessl CLI
npx tessl i tessl/pypi-jsonsdocs
evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10