Skip to main content

JSON Design Patterns

Learning Focus

Consistent JSON design dramatically reduces integration bugs and support tickets. Apply these patterns from the start of any project.

Naming Conventions​

ConventionExampleEcosystem
camelCase (recommended)"firstName"JavaScript, REST APIs
snake_case"first_name"Python, some APIs
PascalCase"FirstName"C# / .NET APIs
kebab-case"first-name"Avoid — invalid in Python identifiers

Pick one and enforce it. Use camelCase for public APIs.

Date and Time​

Always use ISO 8601 strings in UTC:

{
"createdAt": "2024-01-15T08:30:00Z",
"updatedAt": "2024-01-15T14:22:31.456Z",
"scheduledFor": "2024-02-01T00:00:00+08:00",
"dateOnly": "2024-01-15"
}

Never use non-standard formats ("Jan 15, 2024") or undocumented Unix timestamps.

Empty vs Null Collections​

// ✓ Preferred — client can iterate without null-check
{ "tags": [], "items": [] }

// ✗ Avoid — client must null-check before iteration
{ "tags": null, "items": null }

String IDs for Large Integers​

// ✓ Safe — string ID avoids JS precision loss
{ "id": "9007199254740993", "orderId": "ord_abc123" }

// ✗ Risky — integer > 2^53 loses precision in JavaScript
{ "id": 9007199254740993 }

Backwards-Compatible Schema Evolution​

OperationSafe?Notes
Add optional field✓Clients ignore unknown fields
Add required field✗Breaks existing producers
Remove field✗Breaks existing consumers
Rename field✗Both keys needed during transition
Change value type✗Breaks parsers
Expand enum values✓Clients should handle unknown enums

Idempotency Keys​

For operations that must not be duplicated:

{
"idempotencyKey": "order-9871-payment-1",
"amount": 129.99,
"currency": "USD"
}

Concept Map​

Concept Flow

JSON Design Pillars
├── camelCase keys → Consistent naming
├── ISO 8601 dates → Unambiguous timestamps
├── Empty arrays not null → Safe iteration on client
├── String IDs → No precision loss
├── Schema versioning → Predictable evolution
└── Backwards compatibility → Maintainable API

Common Pitfalls​

PitfallConsequencePrevention
Mixed case in same APIClient mapping errorsEnforce via serialiser config
Timestamp without TZAmbiguous local timeAlways use UTC or include offset
null for empty arrayiterable error on clientDefault to []
Renaming without deprecationBreaks all clientsAdd new field; keep old; deprecate with timeline

What's Next​