DoclingDocument Serialization#
DoclingDocument supports multi-format serialization through methods defined directly on the model in docling_core/types/doc/document.py. All serialization/deserialization paths funnel through Pydantic model validators that enforce version compatibility, reference uniqueness, and tree integrity on every load. This topic covers those mechanics; for the modular serializer plugin system (Markdown, HTML, LaTeX, etc.), see Document Serialization Architecture.
Serialization Formats#
JSON and YAML#
JSON and YAML are the two round-trippable native formats — both serialize to/from the full Pydantic schema with all fields intact.
save_as_json(filename, image_mode, indent, coord_precision, confid_precision)— writes viaexport_to_dict()+json.dumps().image_modecontrols how images are stored:EMBEDDED(default, base64 inline) orREFERENCED(files written to a siblingartifacts_dir).load_from_json(filename)— delegates tocls.model_validate_json(filename.read_text(...)), which triggers all Pydantic validators on load.save_as_yaml(filename, image_mode, ...)— same dict pipeline, serialized withyaml.dump().load_from_yaml(filename)— parses withyaml.SafeLoaderthen callsDoclingDocument.model_validate(data).
export_to_dict() is the shared low-level primitive: it calls Pydantic model_dump(mode="json", by_alias=True, exclude_none=True) and injects optional serialization context for coordinate/confidence rounding.
A custom @model_serializer suppresses empty field_regions and field_items from the output dict to keep the JSON compact.
DocTags#
DocTags is an XML-like token format used by vision models (e.g. SmolDocling).
export_to_doctags(add_location, add_cell_location, add_cell_text, add_caption, ...)— delegates toDocTagsDocSerializer.save_as_doctags(filename)— writes the export to disk.load_from_doctags(doctag_document, document_name)— static method; accepts aDocTagsDocument(built from per-page(tokens_str, PIL.Image)pairs) and converts it to aDoclingDocumentusing the sameadd_*builder API.
DocLang#
DocLang is an XML semantic markup format designed for LLM/VLM compatibility, currently at version 0.7.
export_to_doclang(*, add_named_groups=False)— returns serialized DocLang XML as astr. Whenadd_named_groupsisTrue, plainGroupItemelements are serialized as explicit<group name="...">elements; whenFalse(default), groups are transparent and only their children are emitted.save_as_doclang(filename, *, add_named_groups=False)— writes to a.dclg.xmlfile. Theadd_named_groupsparameter is passed through toexport_to_doclang().save_as_doclang_archive(filename, *, artifacts_dir=None, validate=False, add_named_groups=False)— creates a.dclxOPC archive. Images are always stored asREFERENCED, written underassets/; page images go underpages/. Whenadd_named_groupsisTrue, plainGroupItems are emitted as<group name="...">elements so the grouping survives a round trip. Thedoclang.pack()function assembles the archive.load_from_doclang_archive(filename, validate=False, max_member_size, max_total_size)— extracts the zip safely (with per-member and total size caps at 512 MiB and 2 GiB respectively), optionally runs XSD/Schematron validation, then callsDocLangDocDeserializer().deserialize_str().
Default group serialization behavior: By default, plain GroupItem elements are transparent in DocLang serialization—the structural grouping is lost on a round trip. The add_named_groups parameter allows users to preserve these groups when needed.
Pydantic Validation Hooks on Deserialization#
All load paths (load_from_json, load_from_yaml, load_from_doctags, load_from_doclang_archive, and direct model_validate*) invoke these validators in order:
1. Version Compatibility (@field_validator("version"))#
check_version_is_compatible() rejects documents whose schema version is incompatible with the SDK. The rule: major versions must match exactly, and the document's minor version must not exceed the SDK's. On success, the field is normalized to CURRENT_VERSION.
2. Content Layer Migration (@model_validator(mode="before"))#
transform_to_content_layer() handles backward compatibility for v1.0.0 documents (before content_layer was added to every node). It rewrites page_header and page_footer text items to content_layer = "furniture" inline in the raw dict before Pydantic constructs the model.
3. Unique References (@model_validator(mode="after"))#
_validate_unique_refs() iterates every item in all eight flat lists (groups, texts, pictures, tables, key_value_items, form_items, field_regions, field_items) and verifies that no two share a self_ref. Duplicate refs raise ValueError.
4. Tree Integrity (@model_validator(mode="after"))#
validate_document() calls validate_tree() on both body and furniture to check that parent–child relationships are internally consistent. It also calls _clamp_provenance_bboxes_to_pages() to constrain bounding boxes to their page dimensions.
5. Misplaced List Items (@model_validator(mode="after"))#
validate_misplaced_list_items() auto-repairs ListItems that lack a ListGroup parent: it groups consecutive misplaced items, inserts a new ListGroup in place, and re-adds the items under it. This is a repair, not a rejection.
Image Handling (ImageRefMode)#
All save methods accept an image_mode parameter:
| Mode | Behavior |
|---|---|
EMBEDDED (default for JSON/YAML) | Images base64-encoded inline in the JSON/YAML |
REFERENCED | Images written to <stem>_artifacts/ directory; JSON/YAML holds relative URIs |
.dclx archives always use REFERENCED, with images stored in the archive under assets/ and pages/.
Key Source File#
All serialization/deserialization logic and validators described above are in docling_core/types/doc/document.py. Related serializer implementations live in docling_core/transforms/serializer/ (DocTags, DocLang) and docling_core/transforms/deserializer/ (DocLang round-trip).