Tech/Test

JsonPath란?

주지민 2021. 9. 6. 11:39
반응형

소스코드: https://github.com/json-path/JsonPath

 

GitHub - json-path/JsonPath: Java JsonPath implementation

Java JsonPath implementation. Contribute to json-path/JsonPath development by creating an account on GitHub.

github.com

참고: https://advenoh.tistory.com/28

좋은 블로그 감사합니당...

 

Java Jayway JsonPath 사용법

Gatsby로 블로그 마이그레이션을 하여 이 링크를 클릭하면 해당 포스팅으로 갑니다. 감사합니다. http://blog.advenoh.pe.kr 1. 들어가며 Jayway JsonPath는 Stefan Goessner의 JsonPath 구현을 자바로 포팅한 라..

advenoh.tistory.com


 

JsonPath

  • JsonPath는 json 객체를 탐색하기 위한 표준화된 방법입니다
  • 의존성 설정
    // dependency
    
    <dependency>
        <groupId>com.jayway.jsonpath</groupId>
        <artifactId>json-path</artifactId>
        <version>{version}</version>
    </dependency>​

    • SpringBoot의 test starter 의존성을 사용하면 자동으로 설정이 되어있습니다
      org.springframework.boot:spring-boot-stater-test:{verison}​

 

 

Jayway JsonPath evaluator

Goessner examle Twitter API Webapp 20k { "store": { "book": [ { "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95 }, { "category": "fiction", "author": "Evelyn Waugh", "title": "Sword of Honour", "price": 12.

jsonpath.herokuapp.com

 

  • JsonPath 표현법
    • JsonPath의 대표 표현법으로는 두가지가 있습니다
    • Dot 표현법
      • $.store.book[0].title
    • Bracket 표현법
      • $[’store’][‘book’][0][’title’]
    • 대표 연산자
      연산자 설명
      $ 모든 Path 표현식의 시작, 루트 노드로 부터 시작하는 기호
      @ 처리되고 있는 현재 노드를 나타내고 필터 조건자에서 사용
      * 와일드카드, 모든 요소와 매칭
      . Dot 표현식의 자식노드
      [start:end] 배열 slice 연산자
      [?(<expression>)] 필터 표현식으로 필터 조건자가 참인 경우에 매칭되는 모든 요소를 만을 처리한다
      ex. book[?(@.price == 49.99)]
  • JsonPath 함수
    • JsonPath는 표현식 맨 마지막에 붙여 실행할 수 있는 다양한 함수를 지원합니다
    • 제공 함수
      기능 설명 반환값
      min() 숫자 배열의 최솟값 제공 Double
      max() 숫자 배열의 최댓값 제공 Double
      avg() 숫자 배열의 평균값 제공 Double
      stddev() 숫자 배열의 표준 편차값을 제공 Double
      length() 배열의 길이 제공 Integer
      sum() 숫자 배열의 합계 제공 Double
      keys() 속성의 키값들을 제공 Set<E>
      concat() 입력된 파라미터와 연결한 새로운 객체를 반환 파라미터와 동일한 객체
      append() jsonPath 출력 배열에 새로운 아이템 추가 파라미터와 동일한 객체
  • JsonPath 필터
    • 필터 [?(<expression>)] 표현 식을 가지며 <expression>에는 논리 연산자(ex. ==, <, >)와 기타연산자(ex. in, size, empty)로 true, false 값을 반환하는 표현 식이 들어갑니다
    • $[?(@.age == 23 )] : age가 23인 데이터만 반환한다
    • $[?(@.name == ‘Frank’)] : 이름인 Frank인 데이터만 반환한다
    • 제공 필터
      기능 설명
      == 왼쪽 결과값과 오른쪽 값이 동일한지 비교 ( 단 1과 '1'은 다르다 )
      != 왼쪽 결과값과 오른쪽 값이 동일하지 않은지 비교
      < 왼쪽 결과값보다 오른쪽 값이 클 경우
      <= 왼쪽 결과값보다 오른쪽 값이 크거나 같을 경우
      > 왼쪽 결과값이 오른쪽 값보다 클 경우
      >= 왼쪽 결과값이 오른쪽 값보다 크거나 같을 경우
      =~ 왼쪽 결과값이 오른쪽에 정의된 정규식에 매칭되는 경우
      in 왼쪽 결과값이 오른쪽에 정의된 배열에 포함되는 경우
      nin not in, 왼쪽 결과값이 오른쪽에 정의된 배열에 포함되지 않는 경우
      subsetof 왼쪽 결과값들이 오른쪽에 정의된 배열의 서브셋인 경우
      anyof 왼쪽 결과값들이 오른쪽에 정의된 배열 값 중에 매칭되는게 한개라도 있는 경우
      noneof 왼쪽 결과값들이 오른쪽에 정의된 배열 값 중에 매칭되는게 한개도 없는 경우
      size 왼쪽 결과값의 size(String or array)가 오른쪽 값과 같은 경우
      empty 왼쪽 결과값이 아무 것도 없을 경우

 

JsonPath 예제

  • 예제 Json 소스
    // example
    
    {
      "store": {
        "book": [
          {
            "category": "reference",
            "author": "Nigel Rees",
            "title": "Sayings of the Century",
            "price": 8.95
          },
          {
            "category": "fiction",
            "author": "Evelyn Waugh",
            "title": "Sword of Honour",
            "price": 12.99
          },
          {
            "category": "fiction",
            "author": "Herman Melville",
            "title": "Moby Dick",
            "isbn": "0-553-21311-3",
            "price": 8.99
          },
          {
            "category": "fiction",
            "author": "J. R. R. Tolkien",
            "title": "The Lord of the Rings",
            "isbn": "0-395-19395-8",
            "price": 22.99
          }
        ],
        "bicycle": {
          "color": "red",
          "price": 19.95
        },
        "appendKeys": {
          "author": "joojimin"
        },
        "price": 10.2222
      },
      "expensive": 10,
      "author": "jimin",
      "book": [
        {
          "test": "hello"
        },
        {
          "test": "hello2"
        },
        {
          "test": "hello3"
        }
      ]
    }

 

예제 #1, store 속 book 리스트중 author(작가) 리스트 추출

  • jsonPath 표현식
    // dot 표현식
    $.store.book[*].author
    
    // bracket 표현식
    $['store']['book'][*]['author']​
  • Java test 소스
    // example은 미리 정의된 json 포맷 데이터
    
    @DisplayName("jsonPath Test#1: store 속 book 리스트중 author(작가) 리스트 추출")
    @Test
    void jsonPathTest_1() {
        // given
        List<String> expected = List.of("Nigel Rees",
                                        "Evelyn Waugh",
                                        "Herman Melville",
                                        "J. R. R. Tolkien");
    
        // when
        // List<String> authors = JsonPath.parse(example).read("$.store.book[*].author");
        List<String> authors = JsonPath.parse(example).read("$['store']['book'][*]['author']");
    
        // then
        assertThat(authors).hasSize(4)
                           .containsAnyElementsOf(expected);
    }​

    • json 포맷 문자열의 root부터 시작한다는 $
    • 찾아야하는 첫 번째 depth의 키 'store'
    • 찾아야하는 두 번째 depth의 키 'book'
    • 'book'의 value는 리스트이기 때문에 [start:end], [*] 등의 추가 연산자로 배열의 어느부분을 추출할 것인지 정의
    • 찾아야하는 세 번째 depth의 키 'author'

 

예제 #2, 모든 author 추출

  • jsonPath 표현식
    $..author​
  • Java test 소스
    // test    
        
    @DisplayName("jsonPath Test#2: 모든 author 추출")
    @Test
    void jsonPathTest_2() {
    
        // given
        List<String> expected = List.of("jimin",
                                        "Nigel Rees",
                                        "Evelyn Waugh",
                                        "Herman Melville",
                                        "J. R. R. Tolkien",
                                        "joojimin");
    
        // when
        List<String> authors = JsonPath.parse(example).read("$..author");
    
        // then
        assertThat(authors).hasSize(6).containsAnyElementsOf(expected);
    }​

    • 모든 경로의 author key를 조회하여 값을 리턴한다

 

예제 #3, 최상위 키 store 안의 모든 노드들 출력

  • jsonPath 표현식
    $.store.*​
  • Java test 소스
    // test
    
    @DisplayName("jsonPath Test#3: store 안의 모든 값들")
    @Test
    void jsonPathTest_3() {
    
        // when
        List<String> values = JsonPath.parse(example).read("$.store.*");
    
        // then
        assertThat(values).isNotEmpty();
    }​

    • 반환형은 List<String> or List<Map<String,Object>>  둘 다 가능하다

 

예제 #4, 최상위 키 store 안의 키 값중 price를 전부 추출

  • jsonPath 표현식
    $.store..price​
  • Java test 소스
    // test
        
    @DisplayName("jsonPath Test#4: store 안의 price 키 값 추출")
    @Test
    void jsonPathTest_4() {
         
        // given
        List<Double> expected = List.of(8.95,
                                        12.99,
                                        8.99,
                                        22.99,
                                        19.95,
                                        10.222);
    
        // when
        List<Double> prices = JsonPath.parse(example).read("$.store..price");
    
        // then
        assertThat(prices).hasSize(6)
                          .containsAnyElementsOf(expected);
    }​

    • 문자열이 아니고 숫자형태이기 때문에 Double형의 List로 받은 것을 확인 할 수 있다

 

예제 #5, 모든 book 키 값 배열 중 세 번째 값 추출

  • jsonPath 표현식
    $..book[2]​
    • 0부터 시작하는 인덱스 이기 때문에 0,1,2... 순으로 나아갑니다
  • Java test 소스
    // test
    
    @DisplayName("jsonPath Test#5: 모든 book 안의 3번째 값 추출")
    @Test
    void jsonPathTest_5() {
    
        // when
        List<String> books = JsonPath.parse(example).read("$..book[2]");
    
        // then
        assertThat(books).isNotEmpty();
    }​
    • 결과 값이 array( '[ ]' )로 나온다면 List로 받아야한다
    • 결과 값이 단일 JsonObject( '{ }')로 나온다면 Map<String, Object>로 받자
    • 결과 값이 primitive 값으로 나온다면 해당 타입(String, Double...)에 맞게 결과를 리턴 받아야 한다

 

예제 #6, 모든 book 키 값 배열 중 끝에서 두 번째 값 추출

  • jsonPath 표현식
    $..book[-2] // 끝에서 2번째 값
    
    $..book[-2:] // 끝에서 2개의 값
  • Java test 소스
    // test
    
    @DisplayName("jsonPath Test#6: 모든 book의 끝에서 2번째 값 추출")
    @Test
    void jsonPathTest_6() {
    
        // when
        List<String> books = JsonPath.parse(example).read("$..book[-2]");
    
        // then
        assertThat(books).isNotEmpty();
    }​
  • Java test 소스 2
        
    // test 
    
    @DisplayName("jsonPath Test#6-add: 모든 book의 끝에서 2개의 추출")
    @Test
    void jsonPathTest_6_add() {
    
        // when
        List<String> books = JsonPath.parse(example).read("$..book[-2:]");
    
        // then
        assertThat(books).isNotEmpty();
    }​

 

예제 #7, 모든 book 중에 isbn값을 가지고 있는 객체 추출

  • jsonPath 표현식
    $..book[?(@.isbn)]​

    • $..book: 모든 "book" 키 값중
    • [?(<expression>)]: 해당 expression을 만족하는 모든 요소
    • @.isbn: expression, 해당 객체에 isbn이 있는 경우 만족
    • 즉 모든 "book" 키 값 중 속성으로 isbn을 가지고 있는 객체를 전부 추출
  • Java test 소스
    // test
    
    
    @DisplayName("jsonPath Test#7: 모든 book 중에 isbn값을 가지고 있는 객체 추출")
    @Test
    void jsonPathTest_7() {
    
        // when
        List<String> isns = JsonPath.parse(example).read("$..book[?(@.isbn)]");
    
        // then
        assertThat(isns).hasSize(2);
    }​
728x90
반응형