### Installation Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/README.md Command to install the serpyco-rs library using pip. ```bash $ pip install serpyco-rs ``` -------------------------------- ### Installation Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/README.md Install the serpyco-rs library using pip. ```bash pip install serpyco-rs ``` -------------------------------- ### JsonSchemaExtension Example Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/api-reference/metadata.md Example showing how to attach arbitrary JSON Schema extensions to a field using `JsonSchemaExtension`. This example adds custom properties 'x-custom' and 'examples' to the 'email' field's schema. ```python from dataclasses import dataclass from typing import Annotated from serpyco_rs import Serializer from serpyco_rs.metadata import JsonSchemaExtension @dataclass class User: email: Annotated[str, JsonSchemaExtension({'x-custom': 'pii', 'examples': ['user@example.com']})] age: int serializer = Serializer(User) schema = serializer.get_json_schema() # The 'email' property includes the extensions: # schema['components']['schemas']['User']['properties']['email'] # => {'type': 'string', 'x-custom': 'pii', 'examples': ['user@example.com']} ``` -------------------------------- ### Example for 't' parameter Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/configuration.md Example demonstrating the usage of the 't' parameter to specify the dataclass type. ```python from dataclasses import dataclass from serpyco_rs import Serializer @dataclass class User: name: str age: int serializer = Serializer(User) ``` -------------------------------- ### Example for 'camelcase_fields' parameter Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/configuration.md Example demonstrating the usage of the 'camelcase_fields' parameter to convert field names between snake_case and camelCase. ```python @dataclass class Person: first_name: str last_name: str # With camelcase_fields=True serializer = Serializer(Person, camelcase_fields=True) person = Person(first_name='John', last_name='Doe') print(serializer.dump(person)) # {'firstName': 'John', 'lastName': 'Doe'} print(serializer.load({'firstName': 'Jane', 'lastName': 'Smith'})) # Person(first_name='Jane', last_name='Smith') ``` -------------------------------- ### Configuration Precedence Example Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/configuration.md Demonstrates how field-level annotations override constructor parameters. ```python @dataclass class Address: street: str @dataclass class Person: name: str # Per-field override: NoFormat disables global CamelCase for this field address: Annotated[Address, NoFormat] # Global setting applies to 'name' (camelCase) # But 'address' field keeps snake_case due to NoFormat serializer = Serializer(Person, camelcase_fields=True) ``` -------------------------------- ### Example for 'force_default_for_optional' parameter Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/configuration.md Example demonstrating the usage of the 'force_default_for_optional' parameter to make nullable fields optional during deserialization. ```python @dataclass class Config: name: str # Required timeout: int | None # Normally required, even though nullable retries: int | None = 3 # Optional with default # Without force_default_for_optional serializer1 = Serializer(Config) try: serializer1.load({'name': 'app'}) except SchemaValidationError as e: # 'timeout' is required even though it's nullable print(e.message) # With force_default_for_optional serializer2 = Serializer(Config, force_default_for_optional=True) config = serializer2.load({'name': 'app'}) # Config(name='app', timeout=None, retries=3) ``` -------------------------------- ### Complete Example: IPv4AddressType Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/api-reference/custom_type.md A full example demonstrating the implementation and usage of a CustomType for IPv4Address. ```python from dataclasses import dataclass from ipaddress import IPv4Address, AddressValueError from serpyco_rs import Serializer, CustomType class IPv4AddressType(CustomType[IPv4Address, str]): def serialize(self, value: IPv4Address) -> str: return str(value) def deserialize(self, value: str) -> IPv4Address: try: return IPv4Address(value) except AddressValueError: raise ValueError(f"Invalid IPv4 address: {value}") def get_json_schema(self) -> dict: return { 'type': 'string', 'format': 'ipv4', 'example': '192.168.1.1' } @dataclass class Server: name: str ip: IPv4Address def custom_type_resolver(t): if t is IPv4Address: return IPv4AddressType() return None # Use the custom type resolver serializer = Serializer(Server, custom_type_resolver=custom_type_resolver) # Serialize server = Server(name='web-1', ip=IPv4Address('192.168.1.100')) print(serializer.dump(server)) # {'name': 'web-1', 'ip': '192.168.1.100'} # Deserialize loaded = serializer.load({'name': 'db-1', 'ip': '10.0.0.1'}) print(loaded) # Server(name='db-1', ip=IPv4Address('10.0.0.1')) # JSON Schema print(serializer.get_json_schema()) # { # ... # 'properties': { # 'name': {'type': 'string'}, # 'ip': {'type': 'string', 'format': 'ipv4', 'example': '192.168.1.1'} # } # } ``` -------------------------------- ### Full Custom Type Example Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/README.md Full example demonstrating custom type support for IPv4Address. ```python from dataclasses import dataclass from ipaddress import IPv4Address from serpyco_rs import Serializer, CustomType # Define custom type for IPv4Address class IPv4AddressType(CustomType[IPv4Address, str]): def serialize(self, value: IPv4Address) -> str: return str(value) def deserialize(self, value: str) -> IPv4Address: return IPv4Address(value) def get_json_schema(self): return { 'type': 'string', 'format': 'ipv4', } # Defining custom_type_resolver def custom_type_resolver(t: type) -> CustomType | None: if t is IPv4Address: return IPv4AddressType() return None @dataclass class Data: ip: IPv4Address # Use custom_type_resolver in Serializer serializer = Serializer(Data, custom_type_resolver=custom_type_resolver) ``` -------------------------------- ### Resolver pattern example Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/configuration.md Illustrates the general pattern for a custom type resolver function. ```python def custom_resolver(t: type): if t is MyType1: return MyType1Handler() elif t is MyType2: return MyType2Handler() else: return None ``` -------------------------------- ### Serializer with Constructor Parameters Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/configuration.md Example of creating a serializer using constructor parameters for global settings. ```python serializer1 = Serializer( Person, camelcase_fields=True, omit_none=True, force_default_for_optional=True ) ``` -------------------------------- ### Example Usage Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/README.md Demonstrates basic serialization and deserialization with serpyco-rs. ```python data = Data(ip=IPv4Address('1.1.1.1')) serialized_data = serializer.dump(data) # {'ip': '1.1.1.1'} deserialized_data = serializer.load(serialized_data) # Data(ip=IPv4Address('1.1.1.1')) ``` -------------------------------- ### Resolver Implementation Example Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/api-reference/custom_type.md An example of a custom type resolver function implementation. ```python def custom_type_resolver(t: type) -> CustomType[Any, Any] | None: if t is datetime.time: return TimeType() elif t is MyCustomClass: return MyCustomClassType() return None serializer = Serializer( MyDataclass, custom_type_resolver=custom_type_resolver ) ``` -------------------------------- ### build Method Example Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/api-reference/json_schema_builder.md Example demonstrating how to use the build method to generate a JSON Schema for a User dataclass. ```python from dataclasses import dataclass from serpyco_rs import Serializer, JsonSchemaBuilder @dataclass class User: id: int name: str email: str serializer = Serializer(User) builder = JsonSchemaBuilder() schema = builder.build(serializer) print(schema) # { # '$ref': '#/components/schemas/User', # 'components': { # 'schemas': { # 'User': { # 'type': 'object', # 'properties': { # 'id': {'type': 'integer'}, # 'name': {'type': 'string'}, # 'email': {'type': 'string'} # }, # 'required': ['id', 'name', 'email'] # } # } # } # } ``` -------------------------------- ### get_definitions Method Example Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/api-reference/json_schema_builder.md Example showing how to use get_definitions to retrieve and print schema component definitions. ```python builder = JsonSchemaBuilder() builder.build(serializer) definitions = builder.get_definitions() for name, definition in definitions.items(): print(f"{name}: {definition}") ``` -------------------------------- ### Get JSON Schema Method Example Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/api-reference/custom_type.md Example implementation of the get_json_schema method for a TimedeltaType. ```python def get_json_schema(self) -> dict[str, Any]: return {'type': 'integer', 'minimum': 0, 'description': 'Duration in seconds'} ``` -------------------------------- ### Example for 'omit_none' parameter Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/configuration.md Example demonstrating the usage of the 'omit_none' parameter to exclude fields with None values from serialized output. ```python @dataclass class Contact: name: str email: str | None = None phone: str | None = None # With omit_none=True serializer = Serializer(Contact, omit_none=True) contact = Contact(name='Alice', email=None, phone=None) print(serializer.dump(contact)) # {'name': 'Alice'} # email and phone omitted contact = Contact(name='Bob', email='bob@example.com', phone=None) print(serializer.dump(contact)) # {'name': 'Bob', 'email': 'bob@example.com'} # phone still omitted ``` -------------------------------- ### Serialize Method Example Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/api-reference/custom_type.md Example implementation of the serialize method for a TimedeltaType. ```python from datetime import timedelta from serpyco_rs import CustomType class TimedeltaType(CustomType[timedelta, int]): def serialize(self, value: timedelta) -> int: return int(value.total_seconds()) # ... other methods ``` -------------------------------- ### Custom Type Resolver Example Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/README.md Example of a custom_type_resolver function that supports IPv4Address. ```python def custom_type_resolver(t: type) -> CustomType | None: if t is IPv4Address: return IPv4AddressType() return None ser = Serializer(MyDataclass, custom_type_resolver=custom_type_resolver) ``` -------------------------------- ### ErrorItem Example Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/api-reference/exceptions.md Demonstrates creating an ErrorItem and accessing its message and instance path. ```python error_item = ErrorItem( message="'abc' is shorter than 3 characters", instance_path="user.email" ) print(str(error_item)) # ''abc' is shorter than 3 characters (instance_path='user.email') print(error_item.message) # ''abc' is shorter than 3 characters print(error_item.instance_path) # user.email ``` -------------------------------- ### MinLength / MaxLength Example Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/api-reference/metadata.md Enforce string and sequence length constraints during deserialization. ```python from dataclasses import dataclass from typing import Annotated from serpyco_rs import Serializer from serpyco_rs.metadata import MinLength, MaxLength @dataclass class Account: username: Annotated[str, MinLength(3), MaxLength(20)] tags: Annotated[list[str], MaxLength(5)] serializer = Serializer(Account) # Valid serializer.load({'username': 'alice', 'tags': ['admin', 'staff']}) # OK # Invalid serializer.load({'username': 'ab', 'tags': []}) # SchemaValidationError: 'ab' is shorter than 3 characters ``` -------------------------------- ### Example Dataclass Serialization Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/README.md Demonstrates how to define a dataclass and use serpyco-rs to serialize an instance of it. ```python import dataclasses import serpyco_rs @dataclasses.dataclass class Example: name: str num: int tags: list[str] serializer = serpyco_rs.Serializer(Example) result = serializer.dump(Example(name="foo", num=2, tags=["hello", "world"])) print(result) >> {'name': 'foo', 'num': 2, 'tags': ['hello', 'world']} ``` -------------------------------- ### load Method Example Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/api-reference/serializer.md Illustrates deserializing a dictionary into a dataclass instance using the load method. ```python serializer = Serializer(User) data = {'name': 'Bob', 'age': 25, 'tags': ['user']} user = serializer.load(data) # User(name='Bob', age=25, tags=['user']) ``` -------------------------------- ### Example usage of get_json_schema Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/api-reference/serializer.md An example demonstrating how to use the get_json_schema method to obtain a JSON Schema for a User dataclass. ```python serializer = Serializer(User) schema = serializer.get_json_schema() # { # '$schema': 'https://json-schema.org/draft/2020-12/schema', # 'type': 'object', # 'properties': { # 'name': {'type': 'string'}, # 'age': {'type': 'integer'}, # 'tags': {'type': 'array', 'items': {'type': 'string'}} # }, # 'required': ['name', 'age', 'tags'] # } ``` -------------------------------- ### Min / Max Example Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/api-reference/metadata.md Enforce numeric bounds during deserialization. ```python from dataclasses import dataclass from typing import Annotated from serpyco_rs import Serializer from serpyco_rs.metadata import Min, Max @dataclass class Product: price: Annotated[float, Min(0.01), Max(9999.99)] # 0.01 <= price <= 9999.99 stock: Annotated[int, Min(0, inclusive=False), Max(1000)] # 0 < stock <= 1000 serializer = Serializer(Product) # Valid serializer.load({'price': 9.99, 'stock': 500}) # OK # Invalid serializer.load({'price': 0, 'stock': 1}) # SchemaValidationError: [ErrorItem(message='0 is less than the minimum of 0.01', ...)] ``` -------------------------------- ### Deserialize Method Example Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/api-reference/custom_type.md Example implementation of the deserialize method for a TimedeltaType, including error handling. ```python def deserialize(self, value: int) -> timedelta: if value < 0: raise ValueError("Duration cannot be negative") return timedelta(seconds=value) ``` -------------------------------- ### Serialization Error Example (dump) Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/errors.md Example demonstrating a successful dump operation and catching an AttributeError when the object is corrupted. ```python @dataclass class Data: value: int data = Data(value=42) serializer = Serializer(Data) # dump should always succeed for valid objects result = serializer.dump(data) # {'value': 42} # Error only if object is corrupted del data.value # Corrupt the object try: serializer.dump(data) except AttributeError: print("Object is missing required attribute") ``` -------------------------------- ### Example with CamelCase and NoFormat Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/api-reference/metadata.md Demonstrates how to use CamelCase for the top-level structure and NoFormat for a specific nested field to prevent it from being converted to camelCase. ```python from dataclasses import dataclass from typing import Annotated from serpyco_rs import Serializer from serpyco_rs.metadata import CamelCase, NoFormat @dataclass class Address: street_name: str postal_code: str @dataclass class Person: first_name: str home_address: Annotated[Address, NoFormat] # Override parent format for this field serializer = Serializer(Annotated[Person, CamelCase]) person = Person( first_name='John', home_address=Address(street_name='Main St', postal_code='12345') ) result = serializer.dump(person) # { # 'firstName': 'John', # 'homeAddress': { # 'street_name': 'Main St', # NoFormat prevents camelCase # 'postal_code': '12345' # } # } ``` -------------------------------- ### Basic Usage Example Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/api-reference/json_schema_builder.md An example demonstrating the basic usage of JsonSchemaBuilder to generate a schema for nested dataclasses and save it to a file. ```python from dataclasses import dataclass from serpyco_rs import Serializer, JsonSchemaBuilder @dataclass class Address: street: str city: str zip_code: str @dataclass class Person: name: str age: int addresses: list[Address] serializer = Serializer(Person) builder = JsonSchemaBuilder(add_dialect_uri=True) schema = builder.build(serializer) # Save to file import json with open('schema.json', 'w') as f: json.dump(schema, f, indent=2) ``` -------------------------------- ### Example with ForceDefaultForOptional Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/api-reference/metadata.md Shows how ForceDefaultForOptional ensures that optional fields are deserialized to None if they are not present in the input data. ```python from dataclasses import dataclass from typing import Annotated from serpyco_rs import Serializer from serpyco_rs.metadata import ForceDefaultForOptional @dataclass class Config: name: str timeout: int | None debug: int | None = False serializer = Serializer(Annotated[Config, ForceDefaultForOptional]) # Without ForceDefaultForOptional, 'timeout' would be required result = serializer.load({'name': 'app'}) # Config(name='app', timeout=None, debug=False) ``` -------------------------------- ### Field-Level Custom Logic Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/QUICKSTART.md Example of applying custom serialization logic at the field level using Annotated and CustomEncoder. ```python from dataclasses import dataclass from serpyco_rs import CustomEncoder from typing import Annotated @dataclass class Message: # Field-level, no custom type needed text: Annotated[str, CustomEncoder[str, str]( serialize=str.upper, deserialize=str.lower )] ``` -------------------------------- ### dump Method Example Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/api-reference/serializer.md Demonstrates how to serialize a dataclass instance into a JSON-serializable dictionary using the dump method. ```python from dataclasses import dataclass from serpyco_rs import Serializer @dataclass class User: name: str age: int tags: list[str] serializer = Serializer(User) user = User(name="Alice", age=30, tags=["admin", "staff"]) result = serializer.dump(user) # {'name': 'Alice', 'age': 30, 'tags': ['admin', 'staff']} ``` -------------------------------- ### Serializer with Annotated Metadata Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/configuration.md Example of creating a serializer using Annotated metadata for field-specific settings. ```python serializer2 = Serializer( Annotated[Person, CamelCase, OmitNone, ForceDefaultForOptional] ) ``` -------------------------------- ### Query String Deserialization Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/README.md Example of deserializing query string parameters using serpyco-rs. ```python from dataclasses import dataclass from urllib.parse import parse_qsl from serpyco_rs import Serializer from multidict import MultiDict @dataclass class A: foo: int bar: str ser = Serializer(A) print(ser.load_query_params(MultiDict(parse_qsl('foo=1&bar=2')))) ``` -------------------------------- ### Configure JSON Schema Generation Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/README.md Example of configuring JSON Schema generation with JsonSchemaBuilder. ```python from dataclasses import dataclass from serpyco_rs import Serializer, JsonSchemaBuilder @dataclass class A: foo: int bar: str ser = Serializer(A) builder = JsonSchemaBuilder( add_dialect_uri=False, ref_prefix='#/definitions', ) print(builder.build(ser)) print(builder.get_definitions()) ``` -------------------------------- ### CustomType for IPv4Address Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/README.md Example of defining a CustomType for IPv4Address. ```python from serpyco_rs import CustomType from ipaddress import IPv4Address, AddressValueError class IPv4AddressType(CustomType[IPv4Address, str]): def serialize(self, obj: IPv4Address) -> str: return str(obj) def deserialize(self, data: str) -> IPv4Address: try: return IPv4Address(data) except AddressValueError: raise ValueError(f"Invalid IPv4 address: {data}") def get_json_schema(self) -> dict: return {"type": "string", "format": "ipv4"} ``` -------------------------------- ### SchemaValidationError Example Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/api-reference/exceptions.md Demonstrates catching SchemaValidationError and iterating through its specific errors. ```python from serpyco_rs import SchemaValidationError, ErrorItem try: serializer.load({'age': 'invalid', 'name': ''}) except SchemaValidationError as e: print(e.message) # 'Failed to validate input' for error in e.errors: print(f"- {error.message} at {error.instance_path}") # - '0' is not of type 'integer' at age # - '' is shorter than 1 characters at name ``` -------------------------------- ### Example with Flatten Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/api-reference/metadata.md Illustrates how the Flatten metadata can be used to flatten nested data structures into the parent structure during serialization and reconstruct them during deserialization. ```python from dataclasses import dataclass from typing import Annotated, Any from serpyco_rs import Serializer from serpyco_rs.metadata import Flatten @dataclass class Address: street: str city: str @dataclass class Person: name: str address: Annotated[Address, Flatten] extra: Annotated[dict[str, Any], Flatten] serializer = Serializer(Person) # Serialize: nested fields appear at top level person = Person( name='John', address=Address(street='123 Main', city='NYC'), extra={'phone': '555-1234'} ) print(serializer.dump(person)) # {'name': 'John', 'street': '123 Main', 'city': 'NYC', 'phone': '555-1234'} # Deserialize: fields are reconstructed into nested structures loaded = serializer.load({ 'name': 'Jane', 'street': '456 Oak', 'city': 'LA', 'email': 'jane@example.com' }) ``` -------------------------------- ### ValidationError Example Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/api-reference/exceptions.md Demonstrates catching a ValidationError during data loading. ```python from serpyco_rs import ValidationError try: serializer.load({'age': 'not_an_int'}) except ValidationError as e: print(e.message) # 'Error loading field: age - value is not an integer' ``` -------------------------------- ### Custom Types - Simple Custom Type Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/QUICKSTART.md Provides an example of creating a custom type (IPv4Address) by subclassing CustomType, implementing serialize, deserialize, and get_json_schema methods, and registering it with a custom type resolver. ```python from serpyco_rs import CustomType from ipaddress import IPv4Address class IPv4Type(CustomType[IPv4Address, str]): def serialize(self, value: IPv4Address) -> str: return str(value) def deserialize(self, value: str) -> IPv4Address: return IPv4Address(value) def get_json_schema(self) -> dict: return {'type': 'string', 'format': 'ipv4'} def resolver(t: type): if t is IPv4Address: return IPv4Type() return None serializer = Serializer(MyType, custom_type_resolver=resolver) ``` -------------------------------- ### Max recursion depth example Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/configuration.md Demonstrates setting a maximum recursion depth and how it affects serialization of deeply nested structures. ```python from serpyco_rs import Serializer @dataclass class Node: value: int children: list['Node'] = field(default_factory=list) # Strict recursion limit serializer = Serializer(Node, max_recursion_depth=100) # Build a tree 50 levels deep node = Node(value=0) current = node for i in range(1, 50): child = Node(value=i) current.children = [child] current = child # This succeeds (50 < 100 limit) result = serializer.dump(node) # Build a tree 150 levels deep deep_node = Node(value=0) current = deep_node for i in range(1, 150): child = Node(value=i) current.children = [child] current = child # This raises RecursionError (150 > 100 limit) try: serializer.dump(deep_node) except RecursionError as e: print("Structure too deeply nested") ``` -------------------------------- ### SchemaValidationError Example Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/errors.md Demonstrates catching a SchemaValidationError when multiple validation failures occur. ```python from serpyco_rs import SchemaValidationError, ErrorItem @dataclass class Form: email: str age: int username: str serializer = Serializer(Form) try: # Multiple validation failures serializer.load({ 'email': '', # Too short 'age': 'invalid', # Wrong type 'username': 'ab' # Too short }) except SchemaValidationError as e: print(f"Summary: {e.message}") for error in e.errors: print(f" - {error.message} at {error.instance_path}") ``` -------------------------------- ### load_query_params Method Example Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/api-reference/serializer.md Shows how to deserialize query string parameters into a dataclass instance using load_query_params, with automatic type coercion. ```python from multidict import MultiDict from urllib.parse import parse_qsl serializer = Serializer(User) query_params = MultiDict(parse_qsl('name=Charlie&age=35&tags=user&tags=guest')) user = serializer.load_query_params(query_params) # User(name='Charlie', age=35, tags=['user', 'guest']) ``` -------------------------------- ### Example with OmitNone Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/api-reference/metadata.md Illustrates how OmitNone metadata can be used to exclude optional fields with None values from the serialized output. ```python from dataclasses import dataclass from typing import Annotated from serpyco_rs import Serializer from serpyco_rs.metadata import OmitNone @dataclass class User: name: str email: str | None = None phone: Annotated[str | None, OmitNone] = None serializer = Serializer(User) user = User(name='Alice', email=None, phone=None) result = serializer.dump(user) # {'name': 'Alice', 'email': None} # phone omitted, but email kept ``` -------------------------------- ### Catching Errors Example Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/api-reference/exceptions.md Demonstrates a robust error-catching strategy for both SchemaValidationError and general ValidationError. ```python from serpyco_rs import Serializer, SchemaValidationError, ValidationError serializer = Serializer(MyDataclass) # Catch multi-error validation try: obj = serializer.load(data) except SchemaValidationError as e: # Multiple errors for error in e.errors: print(f"{error.instance_path}: {error.message}") except ValidationError as e: # Single error or other failure print(e.message) ``` -------------------------------- ### Example with CustomEncoder Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/api-reference/metadata.md Demonstrates using CustomEncoder to attach custom serialization and deserialization functions to a field, allowing for transformations like case conversion. ```python from dataclasses import dataclass from typing import Annotated from serpyco_rs import Serializer from serpyco_rs.metadata import CustomEncoder @dataclass class Message: text: Annotated[str, CustomEncoder[str, str]( serialize=str.upper, deserialize=str.lower )] serializer = Serializer(Message) # Dump: applies serialize (uppercase) msg = Message(text='hello') print(serializer.dump(msg)) # {'text': 'HELLO'} # Load: applies deserialize (lowercase) loaded = serializer.load({'text': 'WORLD'}) print(loaded) # Message(text='world') ``` -------------------------------- ### Generate JSON Schema Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/README.md Example of generating JSON Schema for a dataclass using serpyco-rs. ```python from dataclasses import dataclass from serpyco_rs import Serializer @dataclass class A: """Description of A""" foo: int bar: str ser = Serializer(A) print(ser.get_json_schema()) ``` -------------------------------- ### Alias Annotation Example Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/README.md Demonstrates how to use the Alias annotation to override field names during serialization and deserialization. ```python from dataclasses import dataclass from typing import Annotated from serpyco_rs import Serializer from serpyco_rs.metadata import Alias @dataclass class A: foo: Annotated[int, Alias('bar')] ser = Serializer(A) print(ser.load({'bar': 1})) >> A(foo=1) print(ser.dump(A(foo=1))) >> {'bar': 1} ``` -------------------------------- ### Custom type resolver for IPv4Address Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/configuration.md Example of using a custom type resolver to handle serialization and deserialization of `ipaddress.IPv4Address`. ```python from ipaddress import IPv4Address from serpyco_rs import Serializer, CustomType class IPv4AddressType(CustomType[IPv4Address, str]): def serialize(self, value: IPv4Address) -> str: return str(value) def deserialize(self, value: str) -> IPv4Address: return IPv4Address(value) def get_json_schema(self) -> dict: return {'type': 'string', 'format': 'ipv4'} def custom_resolver(t: type): if t is IPv4Address: return IPv4AddressType() return None @dataclass class Server: name: str ip: IPv4Address serializer = Serializer(Server, custom_type_resolver=custom_resolver) server = Server(name='web', ip=IPv4Address('192.168.1.1')) print(serializer.dump(server)) # {'name': 'web', 'ip': '192.168.1.1'} ``` -------------------------------- ### Create a Serializer - With Options Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/QUICKSTART.md Demonstrates creating a Serializer with various options like camelcase_fields, omit_none, force_default_for_optional, naive_datetime_to_utc, max_recursion_depth, and custom_type_resolver. ```python serializer = Serializer( User, camelcase_fields=True, # snake_case ↔ camelCase omit_none=True, # Skip None values in output force_default_for_optional=True, # T | None defaults to None naive_datetime_to_utc=True, # Treat naive datetimes as UTC max_recursion_depth=500, # Depth limit custom_type_resolver=my_resolver # Custom types ) ``` -------------------------------- ### Main Entry Point Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/README.md Illustrates the initialization of the Serializer class with various options and its main operations. ```python from serpyco_rs import Serializer, ValidationError, SchemaValidationError @dataclass class MyType: field: str serializer = Serializer( MyType, camelcase_fields=False, omit_none=False, force_default_for_optional=False, naive_datetime_to_utc=False, custom_type_resolver=None, max_recursion_depth=1000, ) # Main operations obj = serializer.load(data) # dict → Python dict_data = serializer.dump(obj) # Python → dict obj_from_query = serializer.load_query_params(query_dict) # MultiDict → Python schema = serializer.get_json_schema() # Generate JSON Schema (Draft 2020-12) ``` -------------------------------- ### SchemaValidationError String Representation Example Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/api-reference/exceptions.md Shows how to get human-readable and structured string representations of SchemaValidationError. ```python str(error) # Human-readable multi-line format with "- " prefix for each error repr(error) # Structured representation showing SchemaValidationError(...) ``` -------------------------------- ### FieldFormat Annotation Example (CamelCase) Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/README.md Illustrates using FieldFormat annotations like CamelCase and NoFormat to control the casing of serialized field names, allowing Python's snake_case to be mapped to JSON's camelCase. ```python from dataclasses import dataclass from typing import Annotated from serpyco_rs import Serializer from serpyco_rs.metadata import CamelCase, NoFormat @dataclass class B: buz_filed: str @dataclass class A: foo_filed: int bar_filed: Annotated[B, NoFormat] ser = Serializer(Annotated[A, CamelCase]) # or ser = Serializer(A, camelcase_fields=True) print(ser.dump(A(foo_filed=1, bar_filed=B(buz_filed='123')))) >> {'fooFiled': 1, 'barFiled': {'buz_filed': '123'}} print(ser.load({'fooFiled': 1, 'barFiled': {'buz_filed': '123'}})) >> A(foo_filed=1, bar_filed=B(buz_filed='123')) ``` -------------------------------- ### Performance Tip: Reuse Serializers Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/QUICKSTART.md Reusing serializer instances for performance optimization. ```python # Module-level SERIALIZER = Serializer(User) def handle(data): return SERIALIZER.load(data) # Reuse ``` -------------------------------- ### API Documentation with OpenAPI Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/QUICKSTART.md Integrating Serpyco-RS serializers with FastAPI to automatically generate OpenAPI schema documentation. ```python from fastapi import FastAPI from serpyco_rs import Serializer app = FastAPI() class User: name: str age: int serializer = Serializer(User) schema = serializer.get_json_schema() # Use schema for OpenAPI documentation app.openapi_schema = { 'components': { 'schemas': schema.get('components', {}).get('schemas', {}) } } ``` -------------------------------- ### Import Essentials Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/QUICKSTART.md Main classes, error handling, custom type support, schema generation, and metadata for field overrides, numeric bounds, length constraints, union tags, field formatting, None handling, default value forcing, custom encoders, flattening, and schema extensions. ```python from serpyco_rs import ( Serializer, # Main class ValidationError, # Error handling SchemaValidationError, ErrorItem, CustomType, # Custom type support JsonSchemaBuilder, # Schema generation ) from serpyco_rs.metadata import ( Alias, # Field name override Min, Max, # Numeric bounds MinLength, MaxLength, # Length constraints Discriminator, # Union tags CamelCase, NoFormat, # Field formatting OmitNone, KeepNone, # None handling ForceDefaultForOptional, CustomEncoder, # Field-level serialize/deserialize Flatten, # Flatten nested structures JsonSchemaExtension, # Schema extensions ) ``` -------------------------------- ### Recursion Error Example Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/errors.md Example of catching a RecursionError when data nesting exceeds the maximum depth. ```python serializer = Serializer(MyType, max_recursion_depth=100) try: obj = serializer.load(deeply_nested_data) except RecursionError as e: print("Data structure too deep") ``` -------------------------------- ### Configuration via Annotated Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/configuration.md Shows how to apply configuration options like CamelCase, OmitNone, and ForceDefaultForOptional using Annotated. ```python from typing import Annotated from serpyco_rs import Serializer from serpyco_rs.metadata import CamelCase, OmitNone, ForceDefaultForOptional @dataclass class Person: name: str email: str | None = None ``` -------------------------------- ### Development - Running Tests Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/README.md Commands to set up development environment and run tests with Python and Rust coverage. ```bash $ cargo install cargo-llvm-cov $ brew install lcov # or apt-get install lcov $ nox -s coverage ``` -------------------------------- ### Serializer Constructor Parameters Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/configuration.md The Serializer class accepts the following configuration parameters. ```python Serializer( t: type[_T], *, camelcase_fields: bool = False, omit_none: bool = False, force_default_for_optional: bool = False, naive_datetime_to_utc: bool = False, custom_type_resolver: Callable[[Any], CustomType[Any, Any] | None] | None = None, max_recursion_depth: int = 1000, ) ``` -------------------------------- ### Integration with Serializer - Customization Example Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/api-reference/json_schema_builder.md Example of using JsonSchemaBuilder for custom schema generation, disabling the dialect URI and changing the ref prefix. ```python # Default Serializer.get_json_schema() includes $schema URI serializer.get_json_schema() # { # '$schema': 'https://json-schema.org/draft/2020-12/schema', # '$ref': '#/components/schemas/ப்புகளை', # 'components': {...} # } # CustomBuilder without URI, with different ref prefix builder = JsonSchemaBuilder( add_dialect_uri=False, ref_prefix='#/definitions' ) schema = builder.build(serializer) # { # '$ref': '#/definitions/ப்புகளை', # 'components': {'schemas': {...}} # } ``` -------------------------------- ### Alias Example Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/api-reference/metadata.md Overrides the field name used during serialization and deserialization. ```python from dataclasses import dataclass from typing import Annotated from serpyco_rs import Serializer from serpyco_rs.metadata import Alias @dataclass class User: user_id: Annotated[int, Alias('id')] user_name: Annotated[str, Alias('name')] serializer = Serializer(User) # Serialize: Python name → external name user = User(user_id=123, user_name="Alice") print(serializer.dump(user)) # {'id': 123, 'name': 'Alice'} # Deserialize: external name → Python name data = {'id': 456, 'name': 'Bob'} print(serializer.load(data)) # User(user_id=456, user_name='Bob') ``` -------------------------------- ### Validation with Defaults Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/QUICKSTART.md Using force_default_for_optional to ensure default values are applied during loading when fields are missing. ```python from serpyco_rs import Serializer from dataclasses import dataclass @dataclass class Config: host: str port: int = 8000 debug: bool = False timeout: float | None = None serializer = Serializer(Config, force_default_for_optional=True) config = serializer.load({'host': 'localhost'}) # Config(host='localhost', port=8000, debug=False, timeout=None) ``` -------------------------------- ### Debugging: Inspect Schema Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/QUICKSTART.md Printing the generated JSON schema in a human-readable format. ```python import json schema = serializer.get_json_schema() print(json.dumps(schema, indent=2)) ``` -------------------------------- ### ValidationError Example Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/errors.md Demonstrates catching a ValidationError when input data is invalid. ```python from serpyco_rs import Serializer, ValidationError @dataclass class User: age: int serializer = Serializer(User) try: serializer.load({'age': 'not_a_number'}) except ValidationError as e: print(e.message) # Output: "... is not of type 'integer'" ``` -------------------------------- ### Database Model Serialization Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/QUICKSTART.md Serializing database models, including type hints and schema extensions for read-only fields. ```python from serpyco_rs import Serializer from dataclasses import dataclass from datetime import datetime from typing import Annotated @dataclass class User: id: int created_at: Annotated[datetime, JsonSchemaExtension({'readOnly': True})] email: str verified: bool = False serializer = Serializer(User) ``` -------------------------------- ### Performance Tip: Discriminated Unions Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/QUICKSTART.md Using discriminated unions for faster union type handling compared to plain unions. ```python # Fast: discriminated Response = Annotated[Success | Error, Discriminator('status')] # Slower: tries all variants Response = Success | Error ``` -------------------------------- ### Discriminator Example Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/api-reference/metadata.md Tags a Union type to enable efficient variant selection during deserialization. ```python from dataclasses import dataclass from typing import Annotated, Literal, Union from serpyco_rs import Serializer from serpyco_rs.metadata import Discriminator @dataclass class SuccessResponse: status: Literal['success'] data: str @dataclass class ErrorResponse: status: Literal['error'] code: int Response = Annotated[SuccessResponse | ErrorResponse, Discriminator('status')] serializer = Serializer(Response) # Discriminator routes to correct variant success = serializer.load({'status': 'success', 'data': 'Hello'}) # SuccessResponse(status='success', data='Hello') error = serializer.load({'status': 'error', 'code': 404}) # ErrorResponse(status='error', code=404) ``` -------------------------------- ### Configuration Best Practices - Global Settings Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/README.md Use constructor parameters for global serializer settings like camelcase_fields and omit_none. ```python serializer = Serializer(MyType, camelcase_fields=True, omit_none=True) ``` -------------------------------- ### Serialization - Serialize (Python → Dict) Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/QUICKSTART.md Serializes a Python object (User instance) into a dictionary. ```python user = User(name="Alice", age=30) data = serializer.dump(user) # {'name': 'Alice', 'age': 30} ``` -------------------------------- ### Type Aliases with PEP 695 Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/README.md Demonstrates the use of new type alias syntax from PEP 695. ```python from dataclasses import dataclass from serpyco_rs import Serializer # New type alias syntax from PEP 695 type StrList = list[str] type StrKeyDict[T] = dict[str, T] @dataclass class Data: names: StrList values: StrKeyDict[int] ser = Serializer(Data) result = ser.dump(Data(names=['alice', 'bob'], values={'a': 1, 'b': 2})) print(result) >> {'names': ['alice', 'bob'], 'values': {'a': 1, 'b': 2}} ``` -------------------------------- ### Generic Dataclasses with PEP 695 Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/README.md Shows how to use the type parameter syntax from PEP 695 for generic dataclasses. ```python from dataclasses import dataclass from serpyco_rs import Serializer @dataclass class Container[T]: value: T items: list[T] # Usage with concrete type ser = Serializer(Container[int]) result = ser.dump(Container(value=42, items=[1, 2, 3])) print(result) >> {'value': 42, 'items': [1, 2, 3]} loaded = ser.load({'value': 42, 'items': [1, 2, 3]}) print(loaded) >> Container(value=42, items=[1, 2, 3]) ``` -------------------------------- ### Basic Usage Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/README.md Demonstrates basic serialization and deserialization with serpyco-rs. ```python from dataclasses import dataclass from serpyco_rs import Serializer @dataclass class User: name: str age: int email: str serializer = Serializer(User) # Serialize (Python → JSON-serializable dict) user = User(name="Alice", age=30, email="alice@example.com") data = serializer.dump(user) # {'name': 'Alice', 'age': 30, 'email': 'alice@example.com'} # Deserialize (JSON dict → Python dataclass) loaded = serializer.load({'name': 'Bob', 'age': 25, 'email': 'bob@example.com'}) # User(name='Bob', age=25, email='bob@example.com') # Generate JSON Schema schema = serializer.get_json_schema() ``` -------------------------------- ### Custom JSON Schema Generation Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/QUICKSTART.md Customizing JSON schema generation with JsonSchemaBuilder, controlling dialect URI and reference prefix. ```python from serpyco_rs import JsonSchemaBuilder builder = JsonSchemaBuilder( add_dialect_uri=False, # Skip $schema ref_prefix='#/definitions' # Use alternate ref style ) schema = builder.build(serializer) definitions = builder.get_definitions() ``` -------------------------------- ### Error Handling - Collect Errors for UI Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/QUICKSTART.md Shows how to collect validation errors into a map for display in a user interface, returning a 422 status code. ```python try: obj = serializer.load(data) except SchemaValidationError as e: errors_map = {} for error in e.errors: field = error.instance_path.split('.')[0] if field not in errors_map: errors_map[field] = [] errors_map[field].append(error.message) return {'errors': errors_map}, 422 ``` -------------------------------- ### Field Annotations - Basic Annotations Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/QUICKSTART.md Illustrates using Annotated for basic field annotations like overriding external names with Alias, setting numeric bounds with Min/Max, defining string length constraints with MinLength/MaxLength, and applying custom serialization logic with CustomEncoder. ```python from typing import Annotated @dataclass class Form: # Override external name user_id: Annotated[int, Alias('userId')] # Numeric bounds age: Annotated[int, Min(0), Max(150)] # String length username: Annotated[str, MinLength(3), MaxLength(20)] # Custom logic text: Annotated[str, CustomEncoder[str, str](serialize=str.upper)] ``` -------------------------------- ### API Request/Response Serialization Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/QUICKSTART.md Handling API requests and responses with field aliasing for camelCase conversion. ```python from serpyco_rs import Serializer from dataclasses import dataclass from typing import Annotated @dataclass class UserRequest: first_name: Annotated[str, Alias('firstName')] last_name: Annotated[str, Alias('lastName')] serializer = Serializer(UserRequest, camelcase_fields=False) user = serializer.load(request_json) ``` -------------------------------- ### Single Dict Flatten Field Constraint Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/api-reference/metadata.md Example demonstrating how to use `dict[str, Never]` with `Flatten` to enforce that a dataclass has only one flatten field, forbidding additional properties. ```python from dataclasses import dataclass from typing import Annotated from serpyco_rs.metadata import Flatten @dataclass class Strict: name: str _: Annotated[dict[str, Never], Flatten] # No extra fields allowed ``` -------------------------------- ### Date and time formats - datetime.date Load and Dump Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/README.md Shows how to load and dump date objects using serpyco-rs. ```python Serializer(date).load('2022-10-14') # date(2022, 10, 14) Serializer(date).dump(datetime(2022, 10, 13, 12, 34, 56)) # '2022-10-13' ``` -------------------------------- ### Debugging: Test with Schema Validator Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/QUICKSTART.md Manually validating data against the generated schema using the `jsonschema` library. ```python # Validate data against schema manually from jsonschema import validate schema = serializer.get_json_schema() validate(instance=data, schema=schema) ``` -------------------------------- ### Partial Updates Serialization Source: https://github.com/ermakov-oleg/serpyco-rs/blob/master/_autodocs/QUICKSTART.md Implementing partial updates by omitting fields with None values during serialization. ```python from serpyco_rs import Serializer from dataclasses import dataclass @dataclass class UpdateRequest: name: str | None = None email: str | None = None age: int | None = None serializer = Serializer(UpdateRequest, omit_none=True) updates = serializer.dump(obj) # Only non-None fields in output ```