﻿---
title: ES|QL JSON_EXTRACT function
description: 
url: https://www.elastic.co/elastic/docs-builder/docs/3028/reference/query-languages/esql/functions-operators/string-functions/json_extract
products:
  - Elasticsearch
---

# ES|QL JSON_EXTRACT function
<applies-to>
  - Elastic Cloud Serverless: Preview
  - Elastic Stack: Planned
</applies-to>


## Syntax

![Embedded](https://www.elastic.co/elastic/docs-builder/docs/3028/reference/query-languages/esql/images/functions/json_extract.svg)


## Parameters

<definitions>
  <definition term="string">
    A string containing valid JSON, or the `_source` field. If `null`, the function returns `null`.
  </definition>
  <definition term="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. If `null`, the function returns `null`.
  </definition>
</definitions>


## Description

Extracts a value from a JSON string using a subset of [JSONPath](https://datatracker.ietf.org/doc/rfc9535) 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]`).

## Supported types


| string  | path    | result  |
|---------|---------|---------|
| _source | keyword | keyword |
| _source | text    | keyword |
| keyword | keyword | keyword |
| keyword | text    | keyword |
| text    | keyword | keyword |
| text    | text    | keyword |


## Examples

```esql
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:
```esql
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:
```esql
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:
```esql
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:
```esql
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:
```esql
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:
```esql
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:
```esql
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           |