jam.utils.json.serde

Base interface for JSON serialization, providing a mixin class and metadata types.

Core Components

JsonSerde

Base mixin class that adds JSON capabilities to any class:

  • to_json(): Convert instance to JSON-compatible value

  • from_json(): Create instance from JSON-compatible value

  • __json_metadata__(): Get field metadata

JsonFieldMetadata

Configuration class for field serialization:

  • name: Custom JSON field name

  • skip_if_none: Skip field if value is None

  • format: Value formatting (e.g., date format)

Implementation Details

Mixin Usage

Two ways to use the JsonSerde mixin:

  1. Direct inheritance:

@dataclass
class Point(JsonSerde):
    x: int
    y: int
  1. With json_serializable decorator:

@json_serializable
@dataclass
class Point:
    x: int
    y: int

Field Metadata

Field metadata controls serialization:

@dataclass
class Document(JsonSerde):
    # Custom field name
    created: datetime = json_field(
        name="createdAt"
    )

    # Skip None values
    tags: Optional[list[str]] = json_field(
        skip_if_none=True
    )

    # Both options
    metadata: dict = json_field(
        name="meta",
        skip_if_none=True
    )

Error Handling

Exception Types

  • JsonSerializationError: Base serialization error

  • JsonDeserializationError: Base deserialization error

  • JsonFieldError: Field-specific errors

Common Errors

  1. Type mismatch during conversion

  2. Missing required fields

  3. Invalid field values

  4. Format errors (e.g., date parsing)

API Reference

Classes

class jam.utils.json.serde.JsonSerde[source]

Bases: object

Base mixin for JSON serialization.

to_json() Any[source]

Convert to JSON-compatible value.

classmethod from_json(data: Any) T[source]

Create from JSON-compatible value.

classmethod __json_metadata__() Dict[str, JsonFieldMetadata][source]

Get JSON metadata for fields.

class jam.utils.json.serde.JsonFieldMetadata(name: str | None = None, skip_if_none: bool = False, format: str | None = None)[source]

Bases: object

Field customization metadata.

name: str | None = None
skip_if_none: bool = False
format: str | None = None
__init__(name: str | None = None, skip_if_none: bool = False, format: str | None = None) None

Exceptions

class jam.utils.json.serde.JsonSerializationError[source]

Bases: Exception

Base exception for JSON serialization errors.

class jam.utils.json.serde.JsonDeserializationError[source]

Bases: Exception

Base exception for JSON deserialization errors.

class jam.utils.json.serde.JsonFieldError(field_name: str, field_type: Type, message: str)[source]

Bases: JsonSerializationError

Field-specific JSON conversion error.

__init__(field_name: str, field_type: Type, message: str)[source]

Examples

Basic Usage

from dataclasses import dataclass
from jam.utils.json import JsonSerde

@dataclass
class Point(JsonSerde):
    x: int
    y: int

point = Point(1, 2)
data = point.to_json()  # -> {"x": 1, "y": 2}
decoded = Point.from_json(data)  # -> Point(x=1, y=2)

Field Customization

from datetime import datetime
from typing import Optional, List

@dataclass
class Document(JsonSerde):
    id: str
    created: datetime = json_field(
        name="createdAt",
        format="%Y-%m-%d"
    )
    tags: Optional[List[str]] = json_field(
        skip_if_none=True
    )

doc = Document(
    id="123",
    created=datetime.now(),
    tags=["a", "b"]
)
data = doc.to_json()
# -> {
#     "id": "123",
#     "createdAt": "2024-02-11",
#     "tags": ["a", "b"]
# }

Error Handling

try:
    Document.from_json({
        "id": 123,  # Wrong type
        "createdAt": "invalid-date"
    })
except JsonFieldError as e:
    print(e)  # Field 'id' (str): Expected str, got int