Webhooks and logs often land as JSON text in a STRING column, like raw.stripe_webhooks.payload. BigQuery reads it with JSONPath:
JSON_VALUE(payload, '$.type') returns a scalar as STRING: text, numbers and booleans all come back as text.
JSON_QUERY(payload, '$.data.object') returns a piece of JSON (an object or array) as JSON text.
JSON_QUERY_ARRAY(payload, '$.data.object.lines') returns an array you can UNNEST.
Because JSON_VALUE always returns a string, cast numbers before doing maths: CAST(JSON_VALUE(payload, '$.data.object.amount_paid') AS INT64). Stripe sends amounts in pence, so divide by 100.
Older code uses JSON_EXTRACT_SCALAR and JSON_EXTRACT, which do the same as JSON_VALUE and JSON_QUERY. BigQuery also has a native JSON type; this table keeps the text, as many raw landing tables do.