숏컷 코드
$ 전체 JSON 값
$.store.book[0].title 첫 번째 책의 title
$['store']['book'][0] bracket notation
$..title 모든 descendant의 title
$.store.book[?@.price < 10]문법
JSONPath는 하나의 위치가 아니라 결과 목록을 반환한다
JSON Pointer는 /store/book/0/title처럼 한 위치를 정확히 가리키는 데 적합하다. JSONPath는 더 넓은 선택과 추출을 위한 query 문법이다. 같은 표현식이 0개, 1개, 여러 개의 node를 반환할 수 있으므로 결과를 항상 단일 값으로 가정하면 안 된다.
{
"store": {
"book": [
{ "title": "A", "price": 7 },
{ "title": "B", "price": 12 }
]
}
}$.store.book[0].title -> ["A"]
$.store.book[*].title -> ["A", "B"]
$.store.book[?@.price < 10] -> [{ "title": "A", "price": 7 }]root와 current node를 구분해야 filter가 읽힌다
$는 query가 적용되는 전체 JSON 값의 root를 가리킨다. @는 filter 안에서 현재 검사 중인 node를 가리킨다. $.items[?@.active == true]처럼 쓸 때 $는 전체 문서이고, @는 items 배열 안의 각 원소다. 이 구분을 놓치면 filter 조건이 엉뚱한 위치를 보게 된다.
dot notation은 간단하지만 bracket notation이 더 안전한 경우가 있다
dot notation은 $.user.name처럼 읽기 쉽다. 하지만 key에 하이픈, 공백, 점, 숫자로 시작하는 이름이 들어가면 bracket notation이 더 명확하다. 외부 API 응답처럼 field 이름을 통제하지 못하는 경우에는 $.user['display-name'] 같은 형태가 안전하다.
filter와 descendant 검색은 비용과 예측 가능성을 확인해야 한다
.. descendant 검색과 filter selector는 편리하지만 탐색 범위가 넓다. 큰 JSON 문서에서 무분별하게 쓰면 성능 문제가 생기고, 같은 이름의 field가 여러 계층에 있을 때 예상보다 많은 결과를 반환할 수 있다. API 계약이나 테스트 assertion에는 가능한 한 구체적인 경로를 쓰는 편이 안정적이다.
선택 기준
| 상황 | 적합한 선택 |
|---|---|
| 정확히 한 위치를 가리킴 | JSON Pointer |
| 여러 항목 추출 | JSONPath |
| key 이름이 단순함 | dot notation |
| key에 특수 문자 포함 | bracket notation |
| 테스트 assertion | descendant 검색보다 구체 경로 |
공식 참고: RFC 9535: JSONPath, RFC 6901: JSON Pointer
주의할 점
JSONPath 결과를 항상 단일 값으로 처리하면 누락과 중복을 놓치기 쉽습니다. 필터와 wildcard는 결과가 여러 개일 수 있다는 전제를 두고, 검증 코드에서는 기대 개수까지 함께 확인해야 합니다.
실패 예시
- "$..id" 결과에서 첫 번째 값만 사용함
- 결과: user.id와 order.id가 함께 잡혀도 어느 값인지 구분하지 못함
- 대응: "$.user.id"처럼 목적에 맞는 구체 경로를 먼저 사용한다참고 링크
2 sources