BigQuery’s JSON functions let you read, write, and filter semi-structured JSON data stored in STRING or JSON columns.
BigQuery supports a native JSON data type alongside JSON-in-STRING columns. Native JSON lets you store objects and arrays while preserving order and duplicate keys, enabling faster, type-aware parsing.
Use JSON when your source data is unpredictable or has many optional fields.Convert to STRUCTs only when the schema stabilizes and you need columnar performance or strict typing.
Use JSON_VALUE for scalars, JSON_QUERY for objects/arrays, and JSON_EXTRACT for raw JSON.
SELECT JSON_VALUE(shipping_info, '$.carrier') AS carrier
FROM Orders;
Combine UNNEST with JSON_QUERY_ARRAY or JSON_EXTRACT_ARRAY to flatten arrays before filtering.
SELECT o.id, item
FROM Orders AS o,
UNNEST(JSON_QUERY_ARRAY(shipping_info, '$.tracking_events')) AS item;
Use JSON_SET or JSON_INSERT inside an UPDATE statement (Preview feature) to modify specific paths without rewriting the whole document.
UPDATE Orders
SET shipping_info = JSON_SET(shipping_info, '$.status', 'delivered')
WHERE id = 42;
Create materialized views that project heavily used JSON paths, avoid wildcards in JSONPath expressions, and filter early with JSON_VALUE instead of post-filtering.
Avoid treating JSON_VALUE results as JSON; they return STRING.Also watch for NULL vs. empty string when a path is missing.
.
Not directly. Instead, create a materialized view or generated column that stores the extracted value and then cluster on that column.
JSON_VALUE/JSON_QUERY return NULL when a path is missing. Use IFNULL or COALESCE to provide defaults.
Yes. Native JSON avoids repeated parsing and supports predicate pushdown, delivering lower latency and reduced slot usage in most workloads.