--- title: Using JSON in MySQL tags: - mysql - json - database author: name: Zihlu Wang email: real@zihluwang.me --- MySQL (since version 5.7) **does not directly support a data type called `jsonb`**. `jsonb` is a data type specific to PostgreSQL, which stores JSON data in a binary format with pre-parsing for faster access and manipulation during queries. However, MySQL's `JSON` data type is functionally and internally similar to PostgreSQL's `jsonb` in many respects, particularly when it comes to querying data. The `JSON` data type in MySQL was introduced in MySQL 5.7 and has the following characteristics: 1. **Binary Storage**: Like PostgreSQL's `jsonb`, MySQL's `JSON` type data is stored in an **internal binary format** rather than as a plain text string. This makes reading and manipulating JSON data more efficient, as the database does not need to parse text-format JSON strings on every query. 2. **Automatic Validation**: When you insert or update a `JSON` column, MySQL automatically validates that its content is a valid JSON document. If not, it throws an error. 3. **Optimised Storage**: The binary format is also space-optimised, typically more compact than storing JSON in raw text format. MySQL provides a powerful set of functions and operators for querying and manipulating `JSON` data, very similar to what you'd expect from `jsonb`: 1. **`->` (JSON Extract Operator)**: Extracts a value from a JSON document. It returns a JSON value. ```sql SELECT my_json_column->'$.key' FROM my_table; -- Example: extract the name property of a user object -- Assuming my_json_column stores {'user': {'name': 'Alice'}} SELECT json_data->'$.user.name' FROM my_table; ``` 2. **`->>` (JSON Unquote Operator)**: Extracts a value from a JSON document and **automatically unquotes it**, typically returning a scalar value (e.g., string, number). This is equivalent to `JSON_UNQUOTE(JSON_EXTRACT(...))`. ```sql SELECT my_json_column->>'$.key' FROM my_table; -- Example: extract the name property of a user object (returns the string 'Alice' directly) SELECT json_data->>'$.user.name' FROM my_table; ``` 3. **`JSON_EXTRACT(json_doc, path, ...)`**: Explicitly extracts data from a JSON document. ```sql SELECT JSON_EXTRACT(my_json_column, '$.key') FROM my_table; ``` 4. **`JSON_CONTAINS(json_doc, candidate, path)`**: Checks whether a JSON document contains a specified value. ```sql -- Check whether the tags array contains 'backend' -- Assuming my_json_column stores {'tags': ['frontend', 'backend']} SELECT * FROM my_table WHERE JSON_CONTAINS(json_data->'$.tags', '"backend"'); ``` 5. **`JSON_SEARCH(json_doc, one_or_all, search_str, escape_char, path, ...)`**: Returns the path to a specified string within a JSON document. ```sql -- Find the path to a value of 'test' SELECT JSON_SEARCH(my_json_column, 'one', 'test') FROM my_table; ``` 6. **`JSON_TABLE(json_doc, path COLUMNS ... )` (MySQL 8.0 and later)**: A very powerful function that "expands" JSON data into relational rows and columns, ideal for complex queries and reporting. ```sql -- Assuming json_data stores {'items': [{'id': 1, 'name': 'A'}, {'id': 2, 'name': 'B'}]} SELECT * FROM my_table, JSON_TABLE(json_data, '$.items[*]' COLUMNS( itemId INT PATH '$.id', itemName VARCHAR(50) PATH '$.name' )) AS jt; ``` Like PostgreSQL's `jsonb`, efficient querying on JSON fields typically requires indexing. Since the content of JSON fields is dynamic, MySQL does not directly support creating traditional B-tree indexes on a specific internal path of a JSON field. However, you can achieve this through **Virtual Generated Columns**: 1. **Create a Virtual Column**: Define a virtual column whose value is extracted from a specific path in the JSON field. ```sql ALTER TABLE my_table ADD COLUMN user_name VARCHAR(255) AS (json_data->>'$.user.name') VIRTUAL; ``` 2. **Create an Index on the Virtual Column**: This way, when you query `WHERE json_data->>'$.user.name' = 'Alice'`, the MySQL optimiser can use the `idx_user_name` index, significantly improving query performance. ```sql CREATE INDEX idx_user_name ON my_table (user_name); ``` Although MySQL does not have the exact name `jsonb`, its `JSON` data type provides highly similar functionality: binary storage optimisation, automatic validation, and rich query operators and functions. By combining virtual columns with indexes, MySQL can deliver query performance and flexibility comparable to PostgreSQL's `jsonb` when working with JSON data.