CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-jsons

A comprehensive Python library for serializing and deserializing Python objects to and from JSON (dictionaries) with minimal code changes required.

81

1.65x
Overview
Eval results
Files

configuration.mddocs/

Configuration & Control

Advanced configuration options for controlling jsons behavior, including fork management for separate serializer configurations, warning control, verbosity settings, and object transformation utilities.

Capabilities

Fork Management

def fork(fork_inst=StateHolder, name=None):
    """
    Create a separate "fork" of serializers and deserializers with independent configuration.
    
    Parameters:
    - fork_inst: Base StateHolder class to fork from (defaults to main StateHolder)
    - name: Optional name for the new fork (auto-generated if not provided)
    
    Returns:
    type: New fork class that can be used as fork_inst parameter in other functions
    """

Object Transformation

def transform(obj, cls, *, mapper=None, dump_cls=None, dump_args=None, dump_kwargs=None, **kwargs):
    """
    Transform an object to a different type via JSON serialization/deserialization.
    
    Parameters:
    - obj: Object to be transformed
    - cls: Target type to transform into
    - mapper: Optional callable to modify the intermediate JSON dict
    - dump_cls: Optional type to use when dumping obj (instead of obj's actual type)
    - dump_args: Optional list of positional args for dump operation
    - dump_kwargs: Optional dict of keyword args for dump operation
    - **kwargs: Additional arguments passed to load operation
    
    Returns:
    Instance of cls created by transforming obj through JSON
    """

Warning Control

def suppress_warnings(do_suppress=True, fork_inst=None):
    """
    Suppress or enable jsons warnings globally.
    
    Parameters:
    - do_suppress: Bool to control warning suppression (True = suppress, False = enable)
    - fork_inst: Optional fork instance to configure (defaults to main StateHolder)
    
    Returns:
    None
    """

def suppress_warning(code, fork_inst=None):
    """
    Suppress a specific warning by its warning code.
    
    Parameters:
    - code: String code of the specific warning to suppress
    - fork_inst: Optional fork instance to configure
    
    Returns:
    None
    """

Verbosity Control

class Verbosity:
    """
    Enum-like class defining levels of verbosity for serialization output.
    """
    WITH_NOTHING = 0
    WITH_CLASS_INFO = 10  
    WITH_DUMP_TIME = 20
    WITH_EVERYTHING = WITH_CLASS_INFO | WITH_DUMP_TIME
    
    @staticmethod
    def from_value(value):
        """
        Convert various value types to Verbosity instance.
        
        Parameters:
        - value: Value to convert (bool, int, Verbosity, or other)
        
        Returns:
        Verbosity: Corresponding Verbosity level
        """

Usage Examples

Fork Management for Different Configurations

import jsons
from jsons import JsonSerializable
from datetime import datetime
from dataclasses import dataclass

# Create separate forks for different use cases
APIFork = jsons.fork(name="APIConfig")
DebugFork = jsons.fork(name="DebugConfig")

# Configure API fork with timestamp serialization
def api_datetime_serializer(dt: datetime, **kwargs) -> int:
    return int(dt.timestamp())

# Configure debug fork with verbose datetime serialization  
def debug_datetime_serializer(dt: datetime, **kwargs) -> str:
    return f"DateTime({dt.isoformat()}, weekday={dt.strftime('%A')})"

# Register different serializers for each fork
jsons.set_serializer(api_datetime_serializer, datetime, fork_inst=APIFork)
jsons.set_serializer(debug_datetime_serializer, datetime, fork_inst=DebugFork)

@dataclass
class Event:
    name: str
    timestamp: datetime

event = Event("Meeting", datetime(2023, 12, 1, 14, 30, 0))

# Use different forks for different serialization styles
api_json = jsons.dump(event, fork_inst=APIFork)
debug_json = jsons.dump(event, fork_inst=DebugFork)
default_json = jsons.dump(event)  # Uses default fork

print("API format:", api_json)
# {'name': 'Meeting', 'timestamp': 1701435000}

print("Debug format:", debug_json)  
# {'name': 'Meeting', 'timestamp': 'DateTime(2023-12-01T14:30:00, weekday=Friday)'}

print("Default format:", default_json)
# {'name': 'Meeting', 'timestamp': '2023-12-01T14:30:00'}

JsonSerializable with Fork Integration

import jsons
from jsons import JsonSerializable

# Create specialized JsonSerializable classes using forks
APISerializable = JsonSerializable.fork("APISerializable")
InternalSerializable = JsonSerializable.fork("InternalSerializable")

# Configure API fork for external communication
def external_id_serializer(obj_id: int, **kwargs) -> str:
    return f"EXT_{obj_id:08d}"  # External IDs are string-formatted

jsons.set_serializer(external_id_serializer, int, fork_inst=APISerializable)

class APIUser(APISerializable):
    def __init__(self, user_id: int, name: str):
        self.user_id = user_id
        self.name = name

class InternalUser(InternalSerializable):
    def __init__(self, user_id: int, name: str):
        self.user_id = user_id  
        self.name = name

# Same data, different serialization based on fork
api_user = APIUser(12345, "Alice")
internal_user = InternalUser(12345, "Alice")

print("API serialization:", api_user.json)
# {'user_id': 'EXT_00012345', 'name': 'Alice'}

print("Internal serialization:", internal_user.json)  
# {'user_id': 12345, 'name': 'Alice'}

Object Transformation

import jsons
from dataclasses import dataclass
from typing import Dict, Any

@dataclass
class Person:
    first_name: str
    last_name: str
    age: int

@dataclass
class Employee:
    name: str
    employee_age: int
    department: str = "Unassigned"

# Transform Person to Employee with field mapping
def person_to_employee_mapper(person_dict: Dict[str, Any]) -> Dict[str, Any]:
    return {
        'name': f"{person_dict['first_name']} {person_dict['last_name']}",
        'employee_age': person_dict['age'],
        'department': 'New Hire'
    }

person = Person("John", "Doe", 30)

# Transform using mapper function
employee = jsons.transform(person, Employee, mapper=person_to_employee_mapper)
print(employee)
# Employee(name='John Doe', employee_age=30, department='New Hire')

# Transform with different dump class
@dataclass
class PersonSummary:
    first_name: str
    age: int
    # Note: missing last_name field

summary = jsons.transform(person, PersonSummary, dump_cls=PersonSummary)
print(summary)
# PersonSummary(first_name='John', age=30)

Advanced Transformation Examples

import jsons
from dataclasses import dataclass
from typing import List
from datetime import datetime

@dataclass
class LogEntry:
    timestamp: datetime
    level: str
    message: str
    module: str

@dataclass  
class AlertSummary:
    alert_time: str
    severity: str
    description: str
    source: str

# Transform log entries to alert summaries
def log_to_alert_mapper(log_dict):
    severity_map = {'ERROR': 'HIGH', 'WARNING': 'MEDIUM', 'INFO': 'LOW'}
    return {
        'alert_time': log_dict['timestamp'],
        'severity': severity_map.get(log_dict['level'], 'UNKNOWN'),
        'description': f"Alert: {log_dict['message']}", 
        'source': f"Module: {log_dict['module']}"
    }

log_entries = [
    LogEntry(datetime.now(), "ERROR", "Database connection failed", "db_manager"),
    LogEntry(datetime.now(), "WARNING", "High memory usage detected", "monitor"),
    LogEntry(datetime.now(), "INFO", "User login successful", "auth")  
]

# Transform list of logs to list of alerts
alerts = [
    jsons.transform(log, AlertSummary, mapper=log_to_alert_mapper)
    for log in log_entries
]

for alert in alerts:
    print(f"{alert.severity}: {alert.description} ({alert.source})")
# HIGH: Alert: Database connection failed (Module: db_manager)
# MEDIUM: Alert: High memory usage detected (Module: monitor)  
# LOW: Alert: User login successful (Module: auth)

Warning Control

import jsons
from dataclasses import dataclass

@dataclass
class TestClass:
    value: str

# Suppress all warnings
jsons.suppress_warnings(True)

# Code that might generate warnings runs silently
test_obj = TestClass("test")
result = jsons.dump(test_obj)

# Re-enable warnings
jsons.suppress_warnings(False)

# Suppress specific warning by code
jsons.suppress_warning("JSONS001")  # Example warning code

# Fork-specific warning control
debug_fork = jsons.fork("DebugFork")
jsons.suppress_warnings(False, fork_inst=debug_fork)  # Enable warnings for debug fork
jsons.suppress_warnings(True)  # But keep main fork warnings suppressed

Verbosity Control

import jsons
from jsons import Verbosity, JsonSerializable
from dataclasses import dataclass
from datetime import datetime

@dataclass
class DataPoint:
    value: float
    recorded_at: datetime

# Different verbosity levels
data = DataPoint(42.5, datetime.now())

# Minimal output (default)
minimal = jsons.dump(data, verbosity=Verbosity.WITH_NOTHING)
print("Minimal:", minimal)
# {'value': 42.5, 'recorded_at': '2023-12-01T14:30:00.123456'}

# With class information
with_class = jsons.dump(data, verbosity=Verbosity.WITH_CLASS_INFO)
print("With class info:", with_class)
# {'value': 42.5, 'recorded_at': '2023-12-01T14:30:00.123456', '-jsons-class': 'DataPoint'}

# With timestamp
with_time = jsons.dump(data, verbosity=Verbosity.WITH_DUMP_TIME)
print("With dump time:", with_time)
# {'value': 42.5, 'recorded_at': '2023-12-01T14:30:00.123456', '-jsons-dump-time': '2023-12-01T14:30:01.000000'}

# With everything
with_all = jsons.dump(data, verbosity=Verbosity.WITH_EVERYTHING)
print("With everything:", with_all)
# {
#   'value': 42.5, 
#   'recorded_at': '2023-12-01T14:30:00.123456',
#   '-jsons-class': 'DataPoint',
#   '-jsons-dump-time': '2023-12-01T14:30:01.000000'
# }

# Verbosity from different value types
print(Verbosity.from_value(True))   # Verbosity.WITH_EVERYTHING
print(Verbosity.from_value(False))  # Verbosity.WITH_NOTHING
print(Verbosity.from_value(None))   # Verbosity.WITH_NOTHING

Advanced Fork Configuration with JsonSerializable

import jsons
from jsons import JsonSerializable, Verbosity

# Create a specialized debug configuration
DebugSerializable = JsonSerializable.with_dump(
    fork=True,  # Create new fork
    verbosity=Verbosity.WITH_EVERYTHING,
    strict=True
).with_load(
    strict=True,
    fork=False  # Use same fork as dump
)

class DebugModel(DebugSerializable):
    def __init__(self, data: str, version: int):
        self.data = data
        self.version = version

debug_obj = DebugModel("test data", 2)

# Automatically includes verbose information due to fork configuration
debug_json = debug_obj.json
print("Debug JSON includes metadata:", '-jsons-class' in debug_json)  # True

# Deserialization uses same fork configuration
restored = DebugModel.from_json(debug_json)
print("Restored:", restored.data, restored.version)

Complete Configuration Example

import jsons
from jsons import JsonSerializable, Verbosity, KEY_TRANSFORMER_CAMELCASE
from datetime import datetime
from dataclasses import dataclass

# Create a fully configured fork for web API integration
WebAPIFork = jsons.fork("WebAPIConfig")

# Configure datetime serialization for web APIs
def web_datetime_serializer(dt: datetime, **kwargs) -> str:
    return dt.isoformat() + 'Z'  # ISO format with Z suffix

# Configure custom validation for web objects
def web_string_validator(s: str, **kwargs) -> bool:
    if len(s.strip()) == 0:
        raise jsons.ValidationError("Web API strings cannot be empty or whitespace")
    return True

# Register configurations for the web fork
jsons.set_serializer(web_datetime_serializer, datetime, fork_inst=WebAPIFork)
jsons.set_validator(web_string_validator, str, fork_inst=WebAPIFork)
jsons.suppress_warnings(False, fork_inst=WebAPIFork)  # Enable warnings for debugging

# Create a specialized base class  
WebAPISerializable = JsonSerializable.fork("WebAPISerializable").with_dump(
    fork_inst=WebAPIFork,
    key_transformer=KEY_TRANSFORMER_CAMELCASE,
    verbosity=Verbosity.WITH_CLASS_INFO
).with_load(
    fork_inst=WebAPIFork,
    key_transformer=jsons.snakecase,
    strict=True
)

@dataclass
class WebUser(WebAPISerializable):
    user_name: str
    email_address: str
    last_login: datetime
    is_active: bool

user = WebUser(
    user_name="alice_smith",
    email_address="alice@example.com", 
    last_login=datetime.now(),
    is_active=True
)

# Serialization uses all configured settings
web_json = user.json
print("Web API JSON:")
print(web_json)
# {
#   'userName': 'alice_smith',
#   'emailAddress': 'alice@example.com',
#   'lastLogin': '2023-12-01T14:30:00.123456Z',  # Custom format with Z
#   'isActive': True,
#   '-jsons-class': 'WebUser'  # Class info due to verbosity setting
# }

# Deserialization handles validation and key transformation
camel_input = {
    'userName': 'bob_jones',
    'emailAddress': 'bob@example.com',
    'lastLogin': '2023-12-01T15:30:00.000000Z',
    'isActive': False
}

restored_user = WebUser.from_json(camel_input)
print("Restored user:", restored_user.user_name, restored_user.email_address)

Install with Tessl CLI

npx tessl i tessl/pypi-jsons

docs

class-integration.md

configuration.md

core-serialization.md

customization.md

index.md

key-transformation.md

type-system.md

tile.json