|\n| value | number | Yes | Measured value | Any valid IEEE 754 double |\n| unit | enum | Yes | Unit of measurement | One of: celsius, fahrenheit, kelvin, percent, ppm |\n| timestamp | string | Yes | Reading time | ISO 8601 with timezone |\n| metadata | object | No | Key-value pairs | String keys and values |\n\n## Changelog\n| Version | Date | Changes |\n|---------|------|---------|\n| v1 | 2025-03-01 | Initial schema |\n\n## Compatibility\n- **Backwards**: Consumers of v1 will continue to work with future versions\n- **Policy**: Only additive, optional field changes between minor versions\n```\n\n→ Docs auto-gen or in sync w/ schema.\nIf err: docs drift → CI check valid. docs vs schema source.\n\n## Check\n\n- [ ] Schema sys matches use case (JSON Schema, Protobuf, Avro)\n- [ ] All fields: types + desc + constraints\n- [ ] Required vs optional explicit\n- [ ] Evo strategy documented (safe changes, versioning)\n- [ ] Valid. at boundaries\n- [ ] Versioned + changelog\n- [ ] Round-trip: serialize → deserialize → compare, no data loss\n\n## Traps\n\n- **Over-constrain early**: Strict valid. on new schema → blocks iteration. Start permissive (`additionalProperties: true`), tighten later.\n- **No defaults**: Add required field w/o default → breaks existing data. Always defaults for new fields.\n- **Null ignored**: Many schemas sloppy on null/missing. Explicit nullable vs optional.\n- **Version in URL not payload**: Long-lived data (storage, events) → embed ver in data, not just endpoint URL.\n- **Enum exhaustive**: New enum val crashes consumers w/ exhaustive switches. Doc unknown → handle gracefully.\n\n## →\n\n- `serialize-data-formats` — format pick + encode/decode\n- `implement-pharma-serialisation` — pharma (regulatory schemas)\n- `write-validation-documentation` — valid. docs for regulated schemas\n","licenseDocuments":[]}}
Design serialization schemas using JSON Schema, Protocol Buffer definitions, or Apache Avro. Covers schema versioning, backwards compatibility, validation rules, and evolution strategies for long-lived data formats. Use when defining a new API contract or data interchange format, adding fields to an existing schema without breaking consumers, migrating betw…
Independent GitHub snapshot · Automated classification · Original documentation governs
name: design-serialization-schema
locale: caveman-ultra
source_locale: en
source_commit: 82c77053
fence_basis_commit: 82c77053
translator: "Julius Brussee homage — caveman"
translation_date: "2026-04-24"
description: >
Design serialization schemas using JSON Schema, Protocol Buffer definitions,
or Apache Avro. Covers schema versioning, backwards compatibility, validation
rules, and evolution strategies for long-lived data formats. Use when defining
a new API contract or data interchange format, adding fields to an existing
schema without breaking consumers, migrating between schema versions, choosing
between schema systems, or documenting data validation rules for automated
enforcement.
license: MIT
allowed-tools: Read Write Edit Bash Grep Glob
metadata:
author: Philipp Thoss
version: "1.0"
domain: data-serialization
complexity: intermediate
language: multi
tags: json-schema, protobuf, avro, schema-evolution, versioning, compatibility
→ Evo plan documented: safe changes + version reqs.
If err: break unavoidable → version (v1 → v2), parallel support during migration.
Step 4: Implement Valid.
# JSON Schema validation (Python)
from jsonschema import validate, ValidationError
import json
schema = json.load(open("measurement_v1.json"))
def validate_measurement(data: dict) -> list[str]:
"""Validate a measurement against the schema. Returns list of errors."""
errors = []
try:
validate(instance=data, schema=schema)
except ValidationError as e:
errors.append(f"{e.json_path}: {e.message}")
return errors
# Usage
errors = validate_measurement({"sensor_id": "s-01", "value": "not_a_number"})
# → ["$.value: 'not_a_number' is not of type 'number'"]
// TypeScript with Zod (runtime + compile-time)
import { z } from 'zod';
const MeasurementSchema = z.object({
sensor_id: z.string().regex(/^[a-z]+-[0-9]+$/),
value: z.number(),
unit: z.enum(['celsius', 'fahrenheit', 'kelvin', 'percent', 'ppm']),
timestamp: z.string().datetime(),
metadata: z.record(z.string()).optional(),
});
type Measurement = z.infer<typeof MeasurementSchema>;
// Validation
const result = MeasurementSchema.safeParse(inputData);
if (!result.success) {
console.error(result.error.issues);
}
→ Valid. on all incoming data at boundaries (API, ingestion).
If err: log valid. errs w/ full payload (redact sensitive) for debug.
Step 5: Doc Schema
Schema doc page:
# Measurement Schema (v1)
## Overview
Represents a single sensor reading with metadata.
## Fields
| Field | Type | Required | Description | Constraints |
|-------|------|----------|-------------|-------------|
| sensor_id | string | Yes | Unique sensor ID | Pattern: `^[a-z]+-[0-9]+
design-serialization-schema · Skills-SI Market
|
| value | number | Yes | Measured value | Any valid IEEE 754 double |
| unit | enum | Yes | Unit of measurement | One of: celsius, fahrenheit, kelvin, percent, ppm |
| timestamp | string | Yes | Reading time | ISO 8601 with timezone |
| metadata | object | No | Key-value pairs | String keys and values |
## Changelog
| Version | Date | Changes |
|---------|------|---------|
| v1 | 2025-03-01 | Initial schema |
## Compatibility
- **Backwards**: Consumers of v1 will continue to work with future versions
- **Policy**: Only additive, optional field changes between minor versions
→ Docs auto-gen or in sync w/ schema.
If err: docs drift → CI check valid. docs vs schema source.
Check
Schema sys matches use case (JSON Schema, Protobuf, Avro)
All fields: types + desc + constraints
Required vs optional explicit
Evo strategy documented (safe changes, versioning)
Valid. at boundaries
Versioned + changelog
Round-trip: serialize → deserialize → compare, no data loss
Traps
Over-constrain early: Strict valid. on new schema → blocks iteration. Start permissive (additionalProperties: true), tighten later.
No defaults: Add required field w/o default → breaks existing data. Always defaults for new fields.
Null ignored: Many schemas sloppy on null/missing. Explicit nullable vs optional.
Version in URL not payload: Long-lived data (storage, events) → embed ver in data, not just endpoint URL.
Enum exhaustive: New enum val crashes consumers w/ exhaustive switches. Doc unknown → handle gracefully.
→
serialize-data-formats — format pick + encode/decode