JSON (de)serialization, GraphQL and JSON schema generation using Python typing.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Generate JSON Schema and GraphQL schemas directly from Python types. Supports all JSON Schema versions and provides comprehensive GraphQL schema generation with built-in types, decorators, and Relay patterns.
Generate JSON schemas for deserialization and serialization with support for all major JSON Schema versions and comprehensive constraint handling.
def deserialization_schema(
tp: AnyType,
*,
all_refs: bool = True,
version: Optional[JsonSchemaVersion] = None,
aliaser: Optional[Aliaser] = None,
additional_properties: Optional[bool] = None,
refs_set: Optional[RefsSet] = None,
with_definitions_schema: bool = False,
) -> Dict[str, Any]:
"""
Generate JSON schema for deserializing into the given type.
Parameters:
- tp: Type to generate schema for
- all_refs: Include all referenced type definitions
- version: JSON Schema version to use
- aliaser: Function to transform field names
- additional_properties: Allow additional properties in objects
- refs_set: Set to track references for circular handling
- with_definitions_schema: Include full definitions schema
Returns:
JSON Schema as dictionary
"""
def serialization_schema(
tp: AnyType,
*,
all_refs: bool = True,
version: Optional[JsonSchemaVersion] = None,
aliaser: Optional[Aliaser] = None,
additional_properties: Optional[bool] = None,
refs_set: Optional[RefsSet] = None,
with_definitions_schema: bool = False,
) -> Dict[str, Any]:
"""
Generate JSON schema for serializing the given type.
Parameters:
- tp: Type to generate schema for
- all_refs: Include all referenced type definitions
- version: JSON Schema version to use
- aliaser: Function to transform field names
- additional_properties: Allow additional properties in objects
- refs_set: Set to track references for circular handling
- with_definitions_schema: Include full definitions schema
Returns:
JSON Schema as dictionary
"""
def definitions_schema(
types: Iterable[AnyType],
*,
version: Optional[JsonSchemaVersion] = None,
aliaser: Optional[Aliaser] = None,
additional_properties: Optional[bool] = None,
) -> Dict[str, Any]:
"""
Generate schema definitions for multiple types.
Parameters:
- types: Iterable of types to generate definitions for
- version: JSON Schema version to use
- aliaser: Function to transform field names
- additional_properties: Allow additional properties in objects
Returns:
Schema definitions dictionary
"""Support for all major JSON Schema versions with automatic schema formatting.
class JsonSchemaVersion(Enum):
"""Supported JSON Schema versions."""
DRAFT_4 = "http://json-schema.org/draft-04/schema#"
DRAFT_6 = "http://json-schema.org/draft-06/schema#"
DRAFT_7 = "http://json-schema.org/draft-07/schema#"
DRAFT_2019_09 = "https://json-schema.org/draft/2019-09/schema"
DRAFT_2020_12 = "https://json-schema.org/draft/2020-12/schema"Generate complete GraphQL schemas from Python types with support for queries, mutations, subscriptions, and advanced features.
def graphql_schema(
query: Optional[Collection[Callable]] = None,
mutation: Optional[Collection[Callable]] = None,
subscription: Optional[Collection[Callable]] = None,
*,
types: Iterable[AnyType] = (),
directives: Optional[Collection[GraphQLDirective]] = None,
id_types: Optional[AbstractSet[AnyType]] = None,
scalar_serializers: Optional[Mapping[AnyType, ScalarSerializer]] = None,
) -> GraphQLSchema:
"""
Generate GraphQL schema from Python types and functions.
Parameters:
- query: Query operation functions or Query class
- mutation: Mutation operation functions or Mutation class
- subscription: Subscription operation functions or Subscription class
- types: Additional types to include in schema
- directives: Custom GraphQL directives
- id_types: Types to treat as GraphQL ID type
- scalar_serializers: Custom scalar serialization functions
Returns:
GraphQLSchema object from graphql-core
"""Built-in types and base classes for GraphQL schema definition.
class Query:
"""Base class for GraphQL query operations."""
pass
class Mutation:
"""Base class for GraphQL mutation operations."""
pass
class Subscription:
"""Base class for GraphQL subscription operations."""
pass
ID = NewType("ID", str) # GraphQL ID typeDecorators for enhanced GraphQL functionality and type definitions.
def resolver(func: Func) -> Func:
"""
Mark function as GraphQL resolver.
Parameters:
- func: Function to mark as resolver
Returns:
Decorated function
"""
def interface(cls: Cls) -> Cls:
"""
Mark class as GraphQL interface.
Parameters:
- cls: Class to mark as interface
Returns:
Decorated class
"""from dataclasses import dataclass
from typing import List, Optional
from apischema.json_schema import deserialization_schema, JsonSchemaVersion
@dataclass
class User:
id: int
name: str
email: Optional[str] = None
tags: List[str] = field(default_factory=list)
# Generate deserialization schema
schema = deserialization_schema(User)
print(schema)
# {
# "$schema": "https://json-schema.org/draft/2020-12/schema",
# "type": "object",
# "properties": {
# "id": {"type": "integer"},
# "name": {"type": "string"},
# "email": {"type": "string"},
# "tags": {"type": "array", "items": {"type": "string"}, "default": []}
# },
# "required": ["id", "name"],
# "additionalProperties": false
# }
# Use specific JSON Schema version
schema = deserialization_schema(User, version=JsonSchemaVersion.DRAFT_7)
print(schema["$schema"]) # "http://json-schema.org/draft-07/schema#"from apischema import schema
@dataclass
class Product:
name: str = field(metadata=schema(min_len=1, max_len=100))
price: float = field(metadata=schema(min=0, exc_max=10000))
category: str = field(metadata=schema(pattern=r"^[a-z]+$"))
schema_def = deserialization_schema(Product)
print(schema_def["properties"]["name"])
# {"type": "string", "minLength": 1, "maxLength": 100}
print(schema_def["properties"]["price"])
# {"type": "number", "minimum": 0, "exclusiveMaximum": 10000}
print(schema_def["properties"]["category"])
# {"type": "string", "pattern": "^[a-z]+$"}from typing import List
from apischema.graphql import graphql_schema, ID
from graphql import print_schema
@dataclass
class User:
id: ID
name: str
email: str
# Define GraphQL operations as functions
def get_user(id: ID) -> Optional[User]:
"""Get user by ID."""
pass
def list_users(limit: int = 10) -> List[User]:
"""List users with pagination."""
pass
def create_user(name: str, email: str) -> User:
"""Create a new user."""
pass
def update_user(id: ID, name: Optional[str] = None) -> User:
"""Update user information."""
pass
# Generate GraphQL schema
schema = graphql_schema(
query=[get_user, list_users],
mutation=[create_user, update_user],
id_types={UUID} # Treat UUID as GraphQL ID
)
# Print GraphQL SDL
print(print_schema(schema))
# type Query {
# getUser(id: ID!): User
# listUsers(limit: Int = 10): [User!]!
# }
#
# type Mutation {
# createUser(name: String!, email: String!): User!
# updateUser(id: ID!, name: String): User!
# }
#
# type User {
# id: ID!
# name: String!
# email: String!
# }class Query:
def user(self, id: ID) -> Optional[User]:
pass
def users(self, limit: int = 10) -> List[User]:
pass
class Mutation:
def create_user(self, name: str, email: str) -> User:
pass
# Generate schema from classes
schema = graphql_schema(query=Query, mutation=Mutation)from apischema.graphql import interface
@interface
@dataclass
class Node:
id: ID
@dataclass
class User(Node):
name: str
email: str
@dataclass
class Post(Node):
title: str
content: str
author_id: ID
def node(id: ID) -> Optional[Node]:
"""Get any node by ID."""
pass
schema = graphql_schema(query=[node])
print(print_schema(schema))
# interface Node {
# id: ID!
# }
#
# type User implements Node {
# id: ID!
# name: String!
# email: String!
# }@dataclass
class Address:
street: str
city: str
country: str
@dataclass
class Company:
name: str
address: Address
@dataclass
class Employee:
name: str
company: Company
# Generate schema with all referenced types
schema = definitions_schema([Employee, Company, Address])
print(schema.keys()) # dict_keys(['$defs', '$schema'])
print(schema['$defs'].keys()) # dict_keys(['Employee', 'Company', 'Address'])RefsSet = Set[str] # Set for tracking schema references
ScalarSerializer = Callable[[Any], Any] # Function for custom scalar serializationInstall with Tessl CLI
npx tessl i tessl/pypi-apischema