mariadb-syntax-json
Installation
SKILL.md
MariaDB JSON : Type, Functions, Indexing, Validation
Deterministic guidance for working with the JSON type and JSON_* functions in MariaDB. Use this skill to declare valid JSON columns, choose the correct extraction function, index JSON paths through generated columns, merge documents with the correct semantics, and avoid the most damaging MySQL-vs-MariaDB JSON traps.
Quick Reference
- MariaDB JSON is an ALIAS for LONGTEXT, NOT native binary storage like MySQL 5.7.8+. Use
CHECK (JSON_VALID(col))for structural validation. For indexing, use functional indexes on virtual or persistent generated columns ; direct expression-indexes are not supported. This is the single most consequential MySQL divergence (D-010, L-005). Verified : KBjson-data-type/. - ALWAYS add
CHECK (JSON_VALID(col))on every JSON column. Without the CHECK constraint,INSERT INTO t (j) VALUES ('not even json')succeeds silently and breaks every downstreamJSON_EXTRACT. The KB confirms : "the JSON_VALID function can be used as a CHECK constraint" ; from the JSON alias the constraint is wired automatically only when the column type isJSON, not when it isLONGTEXT. - JSON_VALUE returns a SCALAR ; JSON_QUERY returns a JSON sub-tree ; JSON_EXTRACT returns JSON (scalar wrapped or sub-tree). Pick by what you actually need downstream. ALWAYS use JSON_VALUE in
WHERE-clauses and functional indexes : it strips the JSON quoting soWHERE JSON_VALUE(doc,'$.status') = 'open'compares strings, not JSON-quoted strings. Verified : KBjson_value/,json_query/,json_extract/. - Use JSON_MERGE_PATCH for RFC 7396 semantics ; use JSON_MERGE_PRESERVE for array concatenation. NEVER use JSON_MERGE.
JSON_MERGEis the deprecated alias and silently behaves likeJSON_MERGE_PRESERVE, not likeJSON_MERGE_PATCH. Migrations from MySQL 5.7 code that calledJSON_MERGEfor partial-update semantics produce wrong results on MariaDB unless rewritten. Verified : KBjson_merge_patch/,json_merge_preserve/. - JSON_MERGE_PATCH (RFC 7396) : a key whose patch value is JSON
nullis REMOVED from the result. Use this for "PATCH /resource"-style partial updates. UseJSON_REMOVEonly when you want to drop the key by path without a patch document. - Functional indexes on JSON require a virtual or persistent generated column. ALWAYS materialise the expression first, then index the column. Direct
CREATE INDEX ix ON t ((JSON_VALUE(doc,'$.k')))syntax (as in MySQL 8 or PostgreSQL) does NOT parse on MariaDB. Verified : KBgenerated-columns/. - JSON_TABLE (10.6+) converts JSON arrays to relational rows with
NESTED PATHfor hierarchies,FOR ORDINALITYfor row counters, andEXISTS PATHfor boolean existence checks.ON EMPTYandON ERRORacceptNULL | DEFAULT 'literal' | ERROR; both default toNULLwhen omitted. Verified : KBjson_table/. - JSON path uses
$for root,.keyfor member,[N]for index,[*]for all array elements, and**for recursive descent. The recursive descent token is**, NOT..(PostgreSQL / jq syntax) and**must be followed by another step (never the final token). Negative indices[-N]and ranges[M to N]are 10.9+. Verified : KBjsonpath-expressions/. - JSON column collation is
utf8mb4_binand storage isLONGTEXT. Inserts in any other character set MUST be transcoded by the client to utf8mb4 ; an inboundlatin1JSON document with non-ASCII bytes will be mangled. ALWAYS runSET NAMES utf8mb4on the connection. - Row-based replication does NOT work for JSON columns between MySQL master and MariaDB replica. MySQL ships the binary format on the wire ; MariaDB cannot decode it. Use statement-based replication or convert the column to TEXT before replication. Verified : KB
json-data-type/. - JSON comparison semantics differ from MySQL. MariaDB compares JSON columns as strings ; MySQL compares structurally. Two JSON documents that are semantically equal but differ in whitespace or key-order compare as equal in MySQL and unequal in MariaDB. ALWAYS use
JSON_EQUALS(a, b)for structural equality on MariaDB.