Serialization Rules
The platform enforces strict serialization governance to ensure every byte in a response carries semantic meaning. These rules are validated by the contract test suite and applied globally across all profiles, media categories, and cache states.
Empty Object Prohibition
Global Contract
Empty objects ({}) are forbidden in all responses. An empty object communicates no semantic meaning and violates the platform's serialization contract.
// ❌ FORBIDDEN — empty objects
{ "preview": {} }
{ "thumbnail": {} }
{ "metadata": { "imageData": {} } }
{ "assets": { "preview": { "emptyNested": { "child": {} } } } }
// ✅ CORRECT — null for known-but-unavailable
{ "thumbnail": null }
// ✅ CORRECT — omission for unsupported
// (no preview field at all)This rule is enforced recursively — nested empty objects are also forbidden. The serialization sanitizer removes empty object structures at all depths before the response is sent.
Enforcement Across All Contexts
| Context | Enforced |
|---|---|
| FAST profile responses | ✅ |
| STANDARD profile responses | ✅ |
| FULL profile responses | ✅ |
| Cached responses | ✅ |
| 202 Accepted (partial) responses | ✅ |
| All media types (image, video, audio, provider) | ✅ |
Projected responses (?fields=...) | ✅ |
Null Semantics
null has a specific semantic meaning: known-but-unavailable. The enrichment is supported for this media category, registered in the enrichment lifecycle, but hasn't completed yet.
// STANDARD image with pending preview enrichments
{
"preview": {
"thumbnail": null, // supported, registered, pending worker completion
"placeholder": null, // supported, registered, pending worker completion
"palette": null // supported, registered, pending worker completion
}
}Null vs Omission Decision Matrix
| Scenario | Treatment | Meaning |
|---|---|---|
| Enrichment supported, not yet completed | null | Known-but-unavailable |
| Enrichment unsupported for media category | Omitted | Not applicable |
| Namespace with no meaningful data | Omitted | No value to communicate |
| Optional namespace not relevant to profile | Omitted | Projection-hidden |
Sanitization Pipeline
The serialization sanitizer operates on the response just before it's sent to the client:
Raw canonical state
→ Profile projection (field visibility)
→ Null semantic assignment (pending enrichments)
→ Empty object removal (recursive)
→ Nested cleanup (remove objects that became empty after child removal)
→ Final validation (no empty objects at any depth)Sanitizer Behavior
// Input (before sanitization)
{
"keepNull": null, // preserved — null has meaning
"keepObjectWithNull": { "value": null }, // preserved — has meaningful content
"removeEmpty": {}, // removed — empty object
"removeNestedEmpty": { "nested": {} }, // removed — becomes empty after child removal
"keepArray": [{}, { "value": null }, "x"] // array cleaned: empty objects removed from arrays
}
// Output (after sanitization)
{
"keepNull": null,
"keepObjectWithNull": { "value": null },
"keepArray": [{ "value": null }, "x"]
}Meaningfulness Check
An object is considered "meaningful" if it contains at least one property with a non-undefined value. null values are meaningful because they carry semantic information (known-but-unavailable).
isMeaningfulObject({}) // false — empty, no meaning
isMeaningfulObject({ value: null }) // true — null carries semantic meaning
isMeaningfulObject({ key: "val" }) // true — has contentCross-Profile Consistency
The serialization rules are applied after profile projection. This means:
- FULL profile generates the richest payload
- FAST/STANDARD projections remove profile-hidden fields
- Serialization sanitizer removes any empty objects that resulted from projection
- The response is clean regardless of which profile was used
// Example: Cached FULL data projected through FAST
// Before sanitization: projection removes diagnostics, providerData, generated preview
// After sanitization: any empty containers left behind are cleaned
// ❌ This would never happen:
{ "data": { "diagnostics": {} } } // empty after projection
// ✅ This is what happens:
{ "data": { /* diagnostics omitted entirely */ } }Provider Intelligence Serialization
Provider-only responses with empty or malformed payloads are sanitized while preserving meaningful provider-native intelligence:
// Provider response with empty nested structures — sanitized correctly
{
"data": {
"preview": {
"thumbnail": {
"url": "https://i.ytimg.com/vi/abc123xyz89/hqdefault.jpg" // preserved
}
// empty nested objects removed
}
}
}The thumbnail is preserved because it carries provider-native value, while any empty nested structures are removed.