A comprehensive Python library for serializing and deserializing Python objects to and from JSON (dictionaries) with minimal code changes required.
81
Comprehensive support for Python's type system including built-in types, collections, datetime objects, Enum types, Union types, and custom objects. The jsons library provides default serializers and deserializers for all common Python types with intelligent type inference.
jsons automatically handles serialization and deserialization for these Python types:
# Automatic handling of typing module generics:
# List[T], Tuple[T, ...], Dict[K, V], Set[T], FrozenSet[T]
# Union[T1, T2, ...], Optional[T], DefaultDict[K, V]
# Mapping[K, V], Iterable[T]import jsons
from decimal import Decimal
# Primitive types work automatically
data = {
'name': 'John', # str
'age': 30, # int
'height': 5.9, # float
'is_active': True, # bool
'notes': None # NoneType
}
serialized = jsons.dump(data)
restored = jsons.load(serialized, dict)
print(restored == data) # True
# Complex numbers
complex_num = 3 + 4j
serialized = jsons.dump(complex_num)
print(serialized) # {'real': 3.0, 'imag': 4.0}
restored = jsons.load(serialized, complex)
print(restored) # (3+4j)
# Decimal precision
price = Decimal('19.99')
serialized = jsons.dump(price)
print(serialized) # '19.99'
restored = jsons.load(serialized, Decimal)
print(restored == price) # Trueimport jsons
from typing import List, Dict, Tuple, Set, Optional
from collections import defaultdict
# Lists with type hints
numbers: List[int] = [1, 2, 3, 4, 5]
serialized = jsons.dump(numbers)
restored = jsons.load(serialized, List[int])
print(restored) # [1, 2, 3, 4, 5]
# Dictionaries with type hints
scores: Dict[str, int] = {'Alice': 95, 'Bob': 87, 'Charlie': 92}
serialized = jsons.dump(scores)
restored = jsons.load(serialized, Dict[str, int])
print(restored) # {'Alice': 95, 'Bob': 87, 'Charlie': 92}
# Tuples with specific types
coordinates: Tuple[float, float, str] = (40.7128, -74.0060, 'NYC')
serialized = jsons.dump(coordinates)
restored = jsons.load(serialized, Tuple[float, float, str])
print(restored) # (40.7128, -74.006, 'NYC')
# Sets (serialized as lists)
unique_tags: Set[str] = {'python', 'json', 'serialization'}
serialized = jsons.dump(unique_tags)
print(serialized) # ['python', 'json', 'serialization'] (order may vary)
restored = jsons.load(serialized, Set[str])
print(type(restored)) # <class 'set'>
# DefaultDict with factory function preservation
def_dict = defaultdict(list)
def_dict['fruits'].extend(['apple', 'banana'])
def_dict['vegetables'].extend(['carrot', 'broccoli'])
serialized = jsons.dump(def_dict)
restored = jsons.load(serialized, defaultdict)
print(restored['new_key']) # [] (default factory still works)import jsons
from datetime import datetime, date, time, timezone, timedelta
from zoneinfo import ZoneInfo # Python 3.9+
# Datetime objects
now = datetime.now()
serialized = jsons.dump(now)
print(serialized) # '2023-12-01T10:30:00.123456'
restored = jsons.load(serialized, datetime)
print(type(restored)) # <class 'datetime.datetime'>
# Date objects
today = date.today()
serialized = jsons.dump(today)
print(serialized) # '2023-12-01'
restored = jsons.load(serialized, date)
# Time objects
current_time = time(14, 30, 45)
serialized = jsons.dump(current_time)
print(serialized) # '14:30:45'
restored = jsons.load(serialized, time)
# Timezone-aware datetime
utc_time = datetime.now(timezone.utc)
serialized = jsons.dump(utc_time)
restored = jsons.load(serialized, datetime)
print(restored.tzinfo) # timezone.utc
# Timedelta objects
duration = timedelta(days=7, hours=3, minutes=30)
serialized = jsons.dump(duration)
restored = jsons.load(serialized, timedelta)
print(restored.days) # 7
# ZoneInfo (Python 3.9+)
ny_tz = ZoneInfo('America/New_York')
ny_time = datetime.now(ny_tz)
serialized = jsons.dump(ny_time)
restored = jsons.load(serialized, datetime)import jsons
from enum import Enum, IntEnum
from uuid import uuid4, UUID
from pathlib import Path
# Enum types
class Status(Enum):
PENDING = 'pending'
APPROVED = 'approved'
REJECTED = 'rejected'
class Priority(IntEnum):
LOW = 1
MEDIUM = 2
HIGH = 3
status = Status.APPROVED
priority = Priority.HIGH
status_serialized = jsons.dump(status)
priority_serialized = jsons.dump(priority)
print(status_serialized) # 'approved'
print(priority_serialized) # 2
status_restored = jsons.load(status_serialized, Status)
priority_restored = jsons.load(priority_serialized, Priority)
print(status_restored == Status.APPROVED) # True
print(priority_restored == Priority.HIGH) # True
# UUID objects
unique_id = uuid4()
serialized = jsons.dump(unique_id)
print(serialized) # '12345678-1234-5678-1234-567812345678'
restored = jsons.load(serialized, UUID)
print(type(restored)) # <class 'uuid.UUID'>
# Path objects
file_path = Path('/home/user/documents/file.txt')
serialized = jsons.dump(file_path)
print(serialized) # '/home/user/documents/file.txt'
restored = jsons.load(serialized, Path)
print(type(restored)) # <class 'pathlib.PosixPath'>import jsons
from typing import Union, Optional, List
from dataclasses import dataclass
@dataclass
class NumberContainer:
value: Union[int, float, str] # Can be int, float, or str
optional_notes: Optional[str] = None # Can be str or None
# Union types - jsons automatically detects the correct type
containers = [
NumberContainer(42), # int
NumberContainer(3.14), # float
NumberContainer("not_a_number"), # str
NumberContainer(100, "Important note") # with optional field
]
serialized_list = jsons.dump(containers)
print(serialized_list)
# [
# {'value': 42, 'optional_notes': None},
# {'value': 3.14, 'optional_notes': None},
# {'value': 'not_a_number', 'optional_notes': None},
# {'value': 100, 'optional_notes': 'Important note'}
# ]
restored_list = jsons.load(serialized_list, List[NumberContainer])
print(type(restored_list[0].value)) # <class 'int'>
print(type(restored_list[1].value)) # <class 'float'>
print(type(restored_list[2].value)) # <class 'str'>
# Optional types work seamlessly
@dataclass
class User:
username: str
email: Optional[str] = None
user1 = User("alice") # email is None
user2 = User("bob", "bob@example.com") # email provided
users = [user1, user2]
serialized = jsons.dump(users)
restored = jsons.load(serialized, List[User])
print(restored[0].email) # None
print(restored[1].email) # 'bob@example.com'import jsons
from dataclasses import dataclass
from typing import List
@dataclass
class Address:
street: str
city: str
zip_code: str
@dataclass
class Person:
name: str
age: int
address: Address
phone_numbers: List[str]
# Nested custom objects work automatically with type hints
address = Address("123 Main St", "Anytown", "12345")
person = Person("John Doe", 30, address, ["+1-555-0100", "+1-555-0101"])
# Automatic serialization of nested objects
serialized = jsons.dump(person)
print(serialized)
# {
# 'name': 'John Doe',
# 'age': 30,
# 'address': {'street': '123 Main St', 'city': 'Anytown', 'zip_code': '12345'},
# 'phone_numbers': ['+1-555-0100', '+1-555-0101']
# }
# Automatic deserialization with proper type reconstruction
restored = jsons.load(serialized, Person)
print(type(restored.address)) # <class '__main__.Address'>
print(restored.address.city) # 'Anytown'
print(len(restored.phone_numbers)) # 2import jsons
from dataclasses import dataclass
from typing import Dict, List, Optional
from datetime import datetime
@dataclass
class Task:
id: int
title: str
completed: bool
due_date: Optional[datetime] = None
@dataclass
class Project:
name: str
tasks: Dict[str, List[Task]] # Complex nested generic structure
# Complex nested structures with multiple generics
project = Project(
name="Website Redesign",
tasks={
"frontend": [
Task(1, "Create mockups", False, datetime(2023, 12, 15)),
Task(2, "Implement UI", False, datetime(2023, 12, 20))
],
"backend": [
Task(3, "API design", True),
Task(4, "Database schema", False, datetime(2023, 12, 10))
]
}
)
# Serialize complex nested structure
serialized = jsons.dump(project)
print(serialized['tasks']['frontend'][0]['title']) # 'Create mockups'
# Deserialize with full type reconstruction
restored = jsons.load(serialized, Project)
print(type(restored.tasks)) # <class 'dict'>
print(type(restored.tasks['frontend'])) # <class 'list'>
print(type(restored.tasks['frontend'][0])) # <class '__main__.Task'>
print(type(restored.tasks['frontend'][0].due_date)) # <class 'datetime.datetime'>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