Basic Usage
This guide covers the fundamental features of Kajson and how to use it as a drop-in replacement for Python's standard json
module.
Importing Kajson
You can import Kajson in two ways:
Basic Serialization and Deserialization
Simple Data Types
Kajson handles all standard JSON data types just like the standard json
module:
import kajson
# Basic types
data = {
"string": "Hello, World!",
"number": 42,
"float": 3.14159,
"boolean": True,
"null": None,
"list": [1, 2, 3],
"dict": {"nested": "value"}
}
# Serialize to JSON string
json_str = kajson.dumps(data)
# Deserialize back to Python object
restored = kajson.loads(json_str)
assert data == restored # Perfect reconstruction
Formatting Options
Kajson supports all the standard formatting options:
import kajson
data = {"name": "Alice", "age": 30, "skills": ["Python", "JavaScript"]}
# Pretty printing with indentation
print(kajson.dumps(data, indent=2))
# Compact output without spaces
print(kajson.dumps(data, separators=(',', ':')))
# Sort keys alphabetically
print(kajson.dumps(data, sort_keys=True))
# Combine options
print(kajson.dumps(data, indent=4, sort_keys=True))
Working with Files
Writing JSON to Files
import kajson
data = {
"users": [
{"id": 1, "name": "Alice"},
{"id": 2, "name": "Bob"}
],
"total": 2
}
# Write to file
with open("data.json", "w") as f:
kajson.dump(data, f, indent=2)
# Alternative: dumps then write
json_str = kajson.dumps(data, indent=2)
with open("data2.json", "w") as f:
f.write(json_str)
Reading JSON from Files
import kajson
# Read from file
with open("data.json", "r") as f:
data = kajson.load(f)
# Alternative: read then loads
with open("data.json", "r") as f:
json_str = f.read()
data = kajson.loads(json_str)
Enhanced Type Support
Unlike standard json
, Kajson automatically handles many Python types:
DateTime Objects
import kajson
from datetime import datetime, date, time, timedelta
data = {
"created_at": datetime.now(),
"date_only": date.today(),
"time_only": time(14, 30, 45),
"duration": timedelta(days=7, hours=3)
}
# Serialize and deserialize
json_str = kajson.dumps(data)
restored = kajson.loads(json_str)
# Types are preserved!
assert isinstance(restored["created_at"], datetime)
assert isinstance(restored["duration"], timedelta)
Lists and Dictionaries with Complex Types
import kajson
from datetime import datetime
# Complex nested structures
data = {
"timestamps": [datetime.now(), datetime(2025, 1, 1)],
"events": {
"start": datetime(2025, 1, 1, 9, 0),
"end": datetime(2025, 1, 1, 17, 0)
}
}
# Works seamlessly
json_str = kajson.dumps(data)
restored = kajson.loads(json_str)
# All nested types preserved
for ts in restored["timestamps"]:
assert isinstance(ts, datetime)
Advanced Options
Custom Separators
import kajson
data = {"a": 1, "b": 2}
# Default separators
default = kajson.dumps(data)
print(default) # {"a": 1, "b": 2}
# Custom separators for compact output
compact = kajson.dumps(data, separators=(',', ':'))
print(compact) # {"a":1,"b":2}
# Custom separators with spaces
spaced = kajson.dumps(data, separators=(', ', ': '))
print(spaced) # {"a": 1, "b": 2}
Ensure ASCII
import kajson
data = {"greeting": "Hello δΈη π"}
# Default: UTF-8 characters preserved
utf8 = kajson.dumps(data)
print(utf8) # {"greeting": "Hello δΈη π"}
# Ensure ASCII: escape non-ASCII characters
ascii_only = kajson.dumps(data, ensure_ascii=True)
print(ascii_only) # {"greeting": "Hello \\u4e16\\u754c \\ud83c\\udf0d"}
Streaming Large Data
For large datasets, you can use generators and iterative parsing:
import kajson
# Serialize large data in chunks
def generate_large_data():
for i in range(1000000):
yield {"id": i, "value": i * 2}
# Write to file efficiently
with open("large_data.json", "w") as f:
f.write("[")
for i, item in enumerate(generate_large_data()):
if i > 0:
f.write(",")
f.write(kajson.dumps(item))
f.write("]")
Common Patterns
Configuration Files
import kajson
from pathlib import Path
class Config:
def __init__(self, config_path="config.json"):
self.path = Path(config_path)
self.data = self.load()
def load(self):
if self.path.exists():
with open(self.path, "r") as f:
return kajson.load(f)
return {}
def save(self):
with open(self.path, "w") as f:
kajson.dump(self.data, f, indent=2)
def get(self, key, default=None):
return self.data.get(key, default)
def set(self, key, value):
self.data[key] = value
self.save()
# Usage
config = Config()
config.set("api_key", "secret123")
config.set("timeout", 30)
API Responses
import kajson
def create_api_response(data, status="success", message=None):
response = {
"status": status,
"timestamp": kajson.dumps(datetime.now()), # Will be properly serialized
"data": data
}
if message:
response["message"] = message
return kajson.dumps(response, indent=2)
# Usage
user_data = {"id": 123, "name": "Alice"}
response = create_api_response(user_data)
print(response)
Best Practices
-
Always use context managers when working with files:
-
Handle exceptions when loading untrusted data:
-
Use appropriate formatting for your use case:
- Human-readable:
indent=2
orindent=4
- Network transmission:
separators=(',', ':')
for compact output - Configuration files:
indent=2, sort_keys=True
for consistency
Next Steps
- Learn about Pydantic Integration for working with data models
- Explore Custom Types to extend Kajson's capabilities
- See Error Handling for robust error management