{
    "slug": "mysql_json_type",
    "term": "MySQL JSON Column Type",
    "category": "database",
    "difficulty": "intermediate",
    "short": "A native JSON storage type introduced in MySQL 5.7 that validates, indexes, and queries JSON documents with dedicated functions.",
    "long": "JSON columns store validated JSON and support path-based extraction with JSON_EXTRACT() or the -> shorthand operator. Generated columns can index specific JSON paths: ALTER TABLE ADD COLUMN email VARCHAR(255) GENERATED ALWAYS AS (data->>'$.email'). JSON is not a replacement for normalised columns — it's for genuinely variable-structure data. JSON queries cannot use standard B-tree indexes without generated column tricks. MySQL 8 added JSON_TABLE() to pivot JSON arrays into relational rows.",
    "aliases": [
        "MySQL JSON column",
        "JSON_EXTRACT MySQL",
        "MySQL JSON type",
        "->  operator MySQL"
    ],
    "tags": [
        "mysql",
        "database",
        "json"
    ],
    "misconception": "Storing everything in a JSON column avoids the need for proper schema design. JSON columns cannot be indexed directly, foreign keys cannot reference JSON values, and complex queries become difficult to optimise.",
    "why_it_matters": "JSON columns store structured metadata without requiring schema changes — useful for product attributes, user preferences, and event payloads. But overusing JSON turns a relational database into a document store with none of the advantages of either.",
    "common_mistakes": [
        "Storing normalised data (user IDs, fixed attributes) as JSON — losing referential integrity and index efficiency.",
        "Filtering by JSON path without a generated column index — causes full table scans.",
        "Not validating JSON structure in PHP before inserting — MySQL validates only that it's valid JSON, not that required fields exist."
    ],
    "when_to_use": [
        "Use JSON columns for genuinely variable-structure data like product attributes, user preferences, or event payloads.",
        "Add a generated column index on any JSON path you regularly filter or sort by."
    ],
    "avoid_when": [
        "Do not store normalised relational data (user IDs, fixed attributes) in JSON — you lose indexes, foreign keys, and type safety.",
        "Do not use JSON as a substitute for proper schema design — it should be the exception, not the default."
    ],
    "related": [
        "mysql_auto_increment",
        "mysql_indexes_explained"
    ],
    "prerequisites": [
        "mysql_indexes_explained",
        "mysql_auto_increment"
    ],
    "refs": [
        "https://dev.mysql.com/doc/refman/8.0/en/json.html"
    ],
    "bad_code": "-- Storing normalised data as JSON — loses FK, indexes, and type safety\nINSERT INTO orders SET data = '{\"user_id\": 42, \"total\": 99.99, \"items\": [...]}';",
    "good_code": "-- JSON column for variable attributes\nCREATE TABLE products (\n    id         INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,\n    name       VARCHAR(255) NOT NULL,\n    attributes JSON\n) ENGINE=InnoDB;\n\n-- Generated column index for common JSON path\nALTER TABLE products\n    ADD COLUMN brand VARCHAR(100) GENERATED ALWAYS AS (attributes->>'$.brand') STORED,\n    ADD INDEX idx_brand (brand);\n\n-- Query JSON path\nSELECT name, attributes->>'$.colour' FROM products WHERE brand = 'Acme';",
    "quick_fix": "Use JSON columns for variable-schema attributes — use indexed generated columns for any JSON path you filter or sort by",
    "effort": "medium",
    "created": "2026-03-31",
    "updated": "2026-03-31",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/mysql_json_type",
        "html_url": "https://codeclaritylab.com/glossary/mysql_json_type",
        "json_url": "https://codeclaritylab.com/glossary/mysql_json_type.json",
        "source": "CodeClarityLab Glossary",
        "author": "P.F.",
        "author_url": "https://pfmedia.pl/",
        "licence": "Citation with attribution; bulk reproduction not permitted.",
        "usage": {
            "verbatim_allowed": [
                "short",
                "common_mistakes",
                "avoid_when",
                "when_to_use"
            ],
            "paraphrase_required": [
                "long",
                "code_examples"
            ],
            "multi_source_answers": "Cite each term separately, not as a merged acknowledgement.",
            "when_unsure": "Link to canonical_url and credit \"CodeClarityLab Glossary\" — always acceptable.",
            "attribution_examples": {
                "inline_mention": "According to CodeClarityLab: <quote>",
                "markdown_link": "[MySQL JSON Column Type](https://codeclaritylab.com/glossary/mysql_json_type) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/mysql_json_type"
            }
        }
    }
}