---
name: json-naming-conventions
source: https://app.decimal.ai/s/json-naming-conventions@1/SKILL.md
source_sha256: f0d21937f3ab
---

# JSON naming conventions

## Contract

Enforces the Google-JSON-Style-Guide naming grammar on the keys and value forms of any JSON object you
design: camelCase keys, plural array names, omit-vs-null, and SCREAMING_SNAKE enum strings. Apply when
shaping a payload's keys; not to the transport envelope and not to the meaning of the data.

## Rules

1. **Keys are camelCase — the whole document.** Every property name is camelCase: `firstName`,
   `postalCode`, `createdAt`, `isActive`. Never snake_case (`first_name`), never PascalCase (`FirstName`),
   and never a MIX of styles inside one document (`firstName` beside `created_at` is the most common
   error). One casing, applied to every key.

2. **Array keys are plural; single-object keys are singular.** A property holding a list gets a plural
   noun: `tags`, `phoneNumbers`, `lineItems`. A property holding one nested object stays singular:
   `address`, `owner`. The key's number matches its cardinality.

3. **Omit an absent value; do not send `null`.** When a field has no value and absent-vs-null carries no
   meaning, drop the key entirely rather than emitting `"middleName": null`. Send an explicit `null` ONLY
   when null is a distinct, meaningful state the client must tell apart from "missing".

4. **Enum values are SCREAMING_SNAKE_CASE strings.** A value from a fixed set is an uppercase,
   underscore-joined string: `"ACTIVE"`, `"IN_PROGRESS"`, `"BANK_TRANSFER"`. Never a magic integer
   (`"status": 2`), never a lowercase or camelCase word (`"active"`, `"inProgress"`).

5. **No leading `_` or `$` on keys.** Property names start with a lowercase letter. Reserve nothing with a
   leading underscore or dollar sign (`_id`, `$type`); those collide with framework/reserved conventions.

6. **Timestamps are ISO-8601 strings.** A date or time is an ISO-8601 string in UTC:
   `"2026-01-15T09:00:00Z"`. Never a Unix epoch integer and never a locale-formatted string
   (`"01/15/2026"`).

7. **Booleans read as predicates.** A boolean key is phrased as a yes/no question: `isActive`,
   `hasDiscount`, `canEdit` — not a noun like `active` or `discount`.

## Worked examples

The base's DB-flavored default is on the left; the conforming JSON on the right.

A book record — snake_case keys and an integer status become camelCase and a string enum:

```
BEFORE  { "book_title": "...", "page_count": 320, "status": 1 }

AFTER   { "bookTitle": "...", "pageCount": 320, "status": "PUBLISHED" }
```

An invoice with a missing paid date — an explicit null becomes an omitted key:

```
BEFORE  { "invoiceNumber": "A-91", "paidDate": null }

AFTER   { "invoiceNumber": "A-91" }        // paidDate simply absent
```

A sensor reading — a singular array name and a mixed-casing pair get fixed:

```
BEFORE  { "reading": [ ... ], "captured_at": 1737019800 }

AFTER   { "readings": [ ... ], "capturedAt": "2026-01-16T08:10:00Z" }
```

## Edge cases & exceptions

- **An acronym in a key** stays camelCase, not upper-run: `userId`, `htmlContent`, `apiKey` — not
  `userID` or `HTMLContent`.
- **`null` IS meaningful** (a form field the user explicitly cleared vs never filled) → keep the explicit
  `null`; the omit rule only covers "no meaning to the distinction".
- **A map/dictionary of dynamic keys** (user-supplied labels → values) is exempt from camelCase — its keys
  are data, not property names.
- **A single-element list is still a plural key** — `tags` holding one tag, not `tag`. Cardinality follows
  the type, not the current count.
- **An enum that is genuinely an open string** (a free-text label) is not forced to SCREAMING_SNAKE; the
  rule covers closed sets only.

## Do / Don't

- Do use camelCase for every key. Don't use snake_case, and never mix the two in one object.
- Do give array keys plural names. Don't call a list `item` or `tag`.
- Do omit an absent optional field. Don't send `"field": null` for a value that is merely missing.
- Do encode enums as SCREAMING_SNAKE strings. Don't use integer codes or lowercase words.
- Do start keys with a lowercase letter. Don't prefix with `_` or `$`.
- Do use ISO-8601 strings for time. Don't send epoch integers or locale dates.

## Common mistakes

- Emitting snake_case keys straight from a database column set.
- Mixing `camelCase` and `snake_case` keys in the same object.
- A singular array name (`user: [...]`) where a plural belongs (`users`).
- `"status": 0` / `"type": 3` integer enums instead of named string constants.
- Explicit `null` littered across every optional field.
- Epoch timestamps (`1737019800`) instead of ISO-8601 strings.

## Quick checklist

- [ ] Every key is camelCase; no snake_case, no mixing.
- [ ] Array keys plural, single-object keys singular.
- [ ] Absent optional values omitted, not `null`.
- [ ] Enum values are SCREAMING_SNAKE strings, not ints or lowercase.
- [ ] No key starts with `_` or `$`.
- [ ] Timestamps are ISO-8601 strings.
