Serialization
osdlabel provides built-in functions for serializing its internal state into a standard JSON document format and deserializing it back.
Document format
Section titled “Document format”osdlabel uses a flat JSON array format for persisting annotations:
[ { "id": "ann-1", "imageId": "sample-1", "contextId": "general", "geometry": { "type": "rectangle", "origin": { "x": 100, "y": 200 }, "width": 300, "height": 150, "rotation": 0 }, "rawAnnotationData": { "format": "fabric", "fabricVersion": "7.2.0", "data": { ... } }, "createdAt": "2026-03-06T12:00:00.000Z", "updatedAt": "2026-03-06T12:00:00.000Z" }]Exporting annotations
Section titled “Exporting annotations”Use serialize() to create a flat array of annotations from the current state:
import { serialize } from 'osdlabel';
const { annotationState } = useAnnotator();
const doc = serialize(annotationState);const json = JSON.stringify(doc, null, 2);
// Save to file, send to API, etc.Importing annotations
Section titled “Importing annotations”Use deserialize() to parse an array and load it into the store:
import { deserialize } from 'osdlabel';
const { actions } = useAnnotator();
const parsed = JSON.parse(jsonString);const { byImage } = deserialize(parsed);actions.loadAnnotations(byImage);deserialize() validates the basic structure of the array and throws SerializationError on invalid input. For deep validation, the library integrates with Valibot in @osdlabel/validation.
Validation
Section titled “Validation”The library provides comprehensive Valibot schemas for annotation validation in the @osdlabel/validation package:
import * as v from 'valibot';import { BaseAnnotationSchema } from '@osdlabel/validation';
if (v.safeParse(BaseAnnotationSchema, unknownData).success) { // unknownData is basically valid BaseAnnotation}Validation checks include:
- Required string fields (
id,imageId, timestamps) - Geometry type and shape validation
- Numeric bounds checking (coordinates, dimensions)
- Extension fields (when composed into a custom schema)
Listening to changes
Section titled “Listening to changes”The onAnnotationsChange callback fires whenever annotations are added, updated, or deleted:
<AnnotatorProvider onAnnotationsChange={(annotations) => { // annotations: Annotation[] — flat list of all annotations saveToBackend(annotations); }}> {/* ... */}</AnnotatorProvider>Getting all annotations
Section titled “Getting all annotations”Use getAllAnnotationsFlat() to extract a flat array from the state at any time:
import { getAllAnnotationsFlat } from '@osdlabel/viewer-api';
const { annotationState } = useAnnotator();const allAnnotations = getAllAnnotationsFlat(annotationState);