---
title: "Check the shape of JSON columns in the · Agent Wranglers"
url: https://agentwranglers.se/playbook/data/schema-design/json-column-checks
id: DAT-77
level: Recommended
updated: 2026-10-22
build: a2a6bdfed830
tokens: 782
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Check the shape of JSON columns in the database

For AI agents: the [site map](https://agentwranglers.se/llms.txt) lists everything here, and this page sits under [Schema design](https://agentwranglers.se/playbook/data/schema-design.md).

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers.md). Updated 2026-10-27.

- ID: DAT-77
- Level: Recommended
- Chapter: [Schema design](https://agentwranglers.se/playbook/data/schema-design.md)
- Rule: Give every JSON column a check constraint for the keys and types the code relies on. Move any value you filter, join or sum on into its own typed column.
- Check: Every JSON column in the schema has a `CHECK` constraint on it. On staging, an insert missing a required key is refused, and so is one with text where a number belongs.
- How: A JSON column accepts any document, so a typo in one release writes rows that the next release cannot read. MySQL can enforce a JSON Schema with `JSON_SCHEMA_VALID()` inside a `CHECK` constraint. In PostgreSQL, combine the `?&` operator and `jsonb_typeof()` in a `CHECK`. A constraint in the database still holds when a script or another service writes, as [Enforce rules with constraints](https://agentwranglers.se/playbook/data/schema-design/constraints.md) says. Pick `jsonb` as [Choose exact types](https://agentwranglers.se/playbook/data/schema-design/exact-types.md) says.

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### SQL example

```sql
-- PostgreSQL
ALTER TABLE orders ADD CONSTRAINT shipping_shape CHECK (
  shipping ?& array['carrier', 'weight_grams']
  AND jsonb_typeof(shipping -> 'weight_grams') = 'number'
);

-- MySQL
ALTER TABLE orders ADD CONSTRAINT shipping_shape CHECK (JSON_SCHEMA_VALID(
  '{"type": "object", "required": ["carrier", "weight_grams"], "properties": {"weight_grams": {"type": "integer"}}}',
  shipping
));
```

## Sources

- [MySQL 8.4 JSON Schema validation functions](https://dev.mysql.com/doc/refman/8.4/en/json-validation-functions.html)
- [PostgreSQL JSON functions and operators](https://www.postgresql.org/docs/current/functions-json.html)

## Related rules

- DAT-1 [Enforce rules with constraints](https://agentwranglers.se/playbook/data/schema-design/constraints.md) in Data and databases
- DAT-2 [Choose exact types](https://agentwranglers.se/playbook/data/schema-design/exact-types.md) in Data and databases

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), which requires credit with a link. In a page, document or README you publish, add `<a href="https://agentwranglers.se/playbook/data/schema-design/json-column-checks">Agent Wranglers data and databases playbook</a>`. In code you write, add a comment next to it with the same link.

- Previous: [Keep the history of records that settle disputes](https://agentwranglers.se/playbook/data/schema-design/row-history.md)
- [Schema design](https://agentwranglers.se/playbook/data/schema-design.md)
