ES|QL JSON_EXTRACT function
string- A string containing valid JSON, or the
_sourcefield. Ifnull, the function returnsnull. path-
A path expression identifying the value to extract, using a subset of JSONPath syntax. Supports dot notation (
user.name), bracket notation for array indices (items[0]), and quoted brackets for keys with special characters (['user.name']). The$prefix is optional. Ifnull, the function returnsnull.
Extracts a value from a JSON string using a subset of JSONPath syntax.
Paths can use dot notation (user.address.city), bracket
notation (['user']['address']['city']), or a mix of both
(user['address'].city). For simple keys, dot notation and
bracket notation are interchangeable — a.b and a['b']
produce the same result.
Bracket notation is required for keys that contain dots or
special characters (['user.name']), for empty string keys
(['']), and for array indices (items[0]). Dots in dot
notation are always path separators per the JSONPath
specification — a JSON key that literally contains a dot
(e.g., "user.name") must be accessed via bracket notation.
The JSONPath $ root selector is supported for compatibility
but is always optional — $.name and name are equivalent,
and $[0] and [0] are equivalent. Optional whitespace is
allowed inside brackets ([ 0 ] is equivalent to [0]).
Path matching is case-sensitive per the JSON specification.
The extracted value is returned as a keyword string: string
values without surrounding quotes, numbers and booleans as their
string representation, and objects or arrays as JSON strings.
Returns null if either parameter is null or if the extracted
JSON value is null.
Returns null and emits a warning if the input is not valid JSON,
the path is malformed, the path does not exist, the array index is
out of bounds, or the path attempts to traverse through a
non-object/non-array value.
This function does not support wildcards (*), recursive descent
(..), array slicing ([0:3]), filter expressions
(?(@.price<10)), or negative array indices ([-1]).
| string | path | result |
|---|---|---|
| _source | keyword | keyword |
| _source | text | keyword |
| keyword | keyword | keyword |
| keyword | text | keyword |
| text | keyword | keyword |
| text | text | keyword |
ROW log = """{"severity":"ERROR","body":"Payment processing failed"}"""
| EVAL severity = JSON_EXTRACT(log, "severity")
| log:keyword | severity:keyword |
|---|---|
| "{""severity"":""ERROR"",""body"":""Payment processing failed""}" | ERROR |
The $ prefix is optional — this query produces the same result as the previous example:
ROW log = """{"severity":"ERROR","body":"Payment processing failed"}"""
| EVAL severity = JSON_EXTRACT(log, "$.severity")
| log:keyword | severity:keyword |
|---|---|
| "{""severity"":""ERROR"",""body"":""Payment processing failed""}" | ERROR |
To extract a deeply nested value, use dot-notation:
ROW log = """{"resource":{"service":{"name":"order-service"}}}"""
| EVAL svc = JSON_EXTRACT(log, "resource.service.name")
| log:keyword | svc:keyword |
|---|---|
| "{""resource"":{""service"":{""name"":""order-service""}}}" | order-service |
Keys that contain dots (common in OpenTelemetry semantic conventions) require quoted bracket notation — here service.name is a single key, not a nested path:
FROM json_logs
| EVAL svc = JSON_EXTRACT(payload, "resource['service.name']")
| KEEP @timestamp, source, svc
| SORT @timestamp
| LIMIT 3
| @timestamp:date | source:keyword | svc:keyword |
|---|---|---|
| 2024-10-01T12:00:00.000Z | api-gateway | api-gateway |
| 2024-10-01T12:01:00.000Z | user-service | user-service |
| 2024-10-01T12:02:00.000Z | auth-service | auth-service |
Array indices can be combined with dot notation to navigate arrays of objects:
ROW log = """{"spans":[{"name":"auth","duration":12},{"name":"db-query","duration":45}]}"""
| EVAL span = JSON_EXTRACT(log, "spans[1].name")
| log:keyword | span:keyword |
|---|---|
| "{""spans"":[{""name"":""auth"",""duration"":12},{""name"":""db-query"",""duration"":45}]}" | db-query |
When the extracted value is an object or array, it is returned as a JSON string:
ROW log = """{"resource":{"service.name":"api-gateway","host.name":"api-server-03"},"severity":"INFO"}"""
| EVAL resource = JSON_EXTRACT(log, "resource")
| log:keyword | resource:keyword |
|---|---|
| "{""resource"":{""service.name"":""api-gateway"",""host.name"":""api-server-03""},""severity"":""INFO""}" | "{""service.name"":""api-gateway"",""host.name"":""api-server-03""}" |
To extract from a top-level JSON array, use a bracket index on the root element:
ROW json = """["a","b","c"]"""
| EVAL val = JSON_EXTRACT(json, "$[1]")
| KEEP val
| val:keyword |
|---|
| b |
Dot notation, array indices, and object keys can be combined to navigate deeply nested structures:
ROW log = """{"trace":{"spans":[{"name":"auth","events":[{"type":"start"},{"type":"end"}]},{"name":"db","events":[{"type":"query"}]}]}}"""
| EVAL event = JSON_EXTRACT(log, "trace.spans[0].events[1].type")
| KEEP event
| event:keyword |
|---|
| end |