Skip to content

Serializer

Bidirectional serialization layer between domain objects and plain dicts, built on cattrs. It is the bridge between the immutable iris domain and any wire format — JSON (via orjson), MessagePack, a database row mapper, or a REST API response model.

Overview

Why cattrs

All iris domain objects are attrs classes. cattrs understands the attrs structure natively and recurses through nested objects automatically. Custom hooks are registered only for the few cases that need non-default behavior (enums serialized as names, MendelianInheritance as a list of primitives, AliasSet, Metadata, and the omit_if_default cleanup pass).

Converter singleton

variant.py exposes a single module-level converter instance. Import it directly — there is no need to instantiate anything:

from iris.adapters.driven.serializers.variant import converter

The same converter handles both VariantAnnotation and GeneAnnotation and all their nested types.

Roundtrip guarantee

structure(unstructure(obj), type(obj)) == obj holds for all registered types. Empty collections and None fields are omitted on unstructure (payload stays lean) and reconstructed as empty tuples / None on structure.

Usage

from iris.adapters.driven.serializers.variant import converter
from iris.domain.genomics.entities import VariantAnnotation, GeneAnnotation

# Unstructure (domain → wire)
raw = converter.unstructure(variant_annotation)        # → dict
raw_list = [converter.unstructure(va) for va in variants]

# Structure (wire → domain)
va = converter.structure(raw, VariantAnnotation)
gene = converter.structure(raw_gene, GeneAnnotation)

Conversion rules

Python type Unstructure (→ wire) Structure (← wire)
Enum .name (human-readable string) Cls["NAME"]
MendelianInheritance ["AD", "AR"] (primitive member names) SerializableFlag.from_list(...)
tuple[X, …] list[X] tuple(list)
frozenset sorted list frozenset(list)
None / empty collection key omitted None / ()
Metadata {"source": …, "version": …, "data": {…}} Metadata(...)
AliasSet {"names": […], "aliases": {…}} AliasSet(...)
attrs class recursive dict attrs class

Reference

iris.adapters.driven.serializers.variant

cattrs converter for iris genomics domain objects.

Wire format rules

  • Enum → .name string (reversible, readable)
  • tuple[X, …] → list[X] (JSON-compatible)
  • frozenset → sorted list
  • None → omitted key (omit_if_default on attrs fields)
  • Mapping → plain dict
  • attrs class → dict (recursive)

Usage::

from iris.adapters.driven.serializers.variant import converter

raw = converter.unstructure(variant_annotation)  # → dict
va = converter.structure(raw, VariantAnnotation)  # → VariantAnnotation