-
[Java] JSONPath로 JSON 데이터 다루기Java/기타 2024. 8. 17. 10:07반응형
JSONPath는 JSON 데이터를 효율적으로 탐색하고, 특정 값을 추출하거나 필터링하는 쿼리 언어입니다. 이번 포스트에서는 com.jayway.jsonpath 라이브러리 사용하여 Java에서 JSON 데이터를 다루는 방법을 살펴보겠습니다.
JSONPath 개요JSONPath는 JSON 문서를 대상으로 SQL과 유사한 구문을 사용하여 JSON 데이터의 특정 값을 추출할 수 있습니다. 대표적인 JSONPath 구문은 다음과 같습니다.
JSON 경로 설명JSON 경로 설명 $ 루트 객체를 나타냅니다. @ 현재 객체를 나타냅니다. . 또는 [] 자식을 나타냅니다. * 모든 요소를 나타냅니다. .. 모든 하위 요소를 재귀적으로 탐색합니다. ?() 필터링 조건을 나타냅니다. 1. 라이브러리 추가
com.jayway.jsonpath:json-path:2.9.0는 Java에서 JSON 데이터를 다루기 위해 사용하는 라이브러리입니다.
Gradle 설정
build.gradle 파일에 다음과 같이 의존성을 추가합니다.// JSON Path implementation 'com.jayway.jsonpath:json-path:2.9.0'
Maven Repository : https://mvnrepository.com/artifact/com.jayway.jsonpath/json-path
2. 샘플 JSON
다음은 예제에서 사용할 store.json 파일입니다.
{ "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 } }, "expensive": 10 }
3. JSONPath를 사용한 테스트 코드
3_1. JSONPath를 사용하여 JSON 파일에서 작가명을 추출
$.store.book[*].author 표현식은 book 배열 내의 모든 author 필드를 찾아서 반환합니다.@DisplayName("getAuthorsFromJsonFile_Json 파일에서 작가명을 조회") @Test public void testGetAuthorsFromJsonFile() { // Given & When // book 배열 내의 모든 author 필드를 찾아서 반환 List<String> authors = JsonPath.read(json, "$.store.book[*].author"); log.debug("authors : {}", authors); // Then assertAll( () -> assertFalse(authors.isEmpty()) ); }
3_2. JSON 문자열을 Document 객체로 파싱한 후, JSONPath를 사용하여 작가명 추출
@DisplayName("getAuthorsFromDocument_Document 에서 작가명을 조회") @Test void testGetAuthorsFromDocument() { // Given // JSON 문자열을 Document 객체로 파싱 Object document = Configuration.defaultConfiguration().jsonProvider().parse(json); // When // JSONPath를 사용하여 Document 객체에서 작가명을 추출 List<String> authors = JsonPath.read(document, "$.store.book[*].author"); log.debug("authors : {}", authors); // Then assertAll( () -> assertFalse(authors.isEmpty()) ); }
3_3. ReadContext 객체를 이용하여 JSONPath를 통한 작가명 추출@DisplayName("getAuthorsFromReadContext_ReadContext 에서 작가명을 조회") @Test void testGetAuthorsFromReadContext() { // Given // JSON 문자열을 ReadContext 객체로 파싱 ReadContext readContext = JsonPath.parse(json); // When // JSONPath를 사용하여 ReadContext 객체에서 작가명을 추출 List<String> authors = readContext.read("$.store.book[*].author"); log.debug("authors : {}", authors); // Then assertAll( () -> assertFalse(authors.isEmpty()) ); }
3_4. 특정 조건을 만족하는 책 정보 추출
$.store.book[?(@.category == 'fiction' && @.price > 10)] 표현식은 book 배열 내에서 category가 'fiction'이고 price가 10달러를 초과하는 책 객체들을 반환합니다.@DisplayName("getBooks_조건을 추가하여 10달러 초과의 비싼 책을 조회") @Test void testGetBooks() { // Given & When // JSONPath를 사용하여 조건에 따라 책 정보를 추출 List<Map<String, Object>> books = JsonPath .using(Configuration.defaultConfiguration()) .parse(json) .read("$.store.book[?(@.category == 'fiction' && @.price > 10)]", List.class); log.debug("books : {}", books); // Then assertAll( () -> assertFalse(books.isEmpty()) ); }
3_5. JSONPath 필터를 사용하여 특정 조건을 만족하는 책 정보 추출
JSONPath 필터를 사용하여 category가 'fiction'이고 price가 10달러를 초과하는 책 객체들을 반환합니다.@DisplayName("getBooksFiltered" + "_조건(?(@.category == 'fiction' && @.price > 10)을 추가하여 10달러 초과의 비싼 책을 조회") @Test void testGetBooksFiltered() { // Given // 필터 구문을 사용하여 조건을 정의 Filter filter = filter( where("category").is("fiction").and("price").gt(10D) ); // When // JSONPath 필터를 사용하여 조건에 맞는 책 정보를 추출 List<Map<String, Object>> books = JsonPath .using(Configuration.defaultConfiguration()) .parse(json) .read("$.store.book[?]", filter); log.debug("books : {}", books); // Then assertAll( () -> assertFalse(books.isEmpty()) ); }
3_6. JSONPath를 이용하여 JSON 문자열을 객체로 변환
JSONPath를 사용하여 첫 번째 책의 정보를 Book 객체로 변환하고 이를 검증합니다.@DisplayName("getBookDto_JSON 문자열을 BookDto 객체로 변환하여 반환") @Test void testGetBook() { // Given String jsonPath = "$.store.book[0]"; // When // JSON 문자열을 Book 객체로 변환 Book book = JsonPath.parse(json).read(jsonPath, Book.class); log.debug("book : {}", book.toString()); // Then assertAll( () -> assertNotNull(book), () -> assertEquals("reference", book.getCategory()), () -> assertEquals("Nigel Rees", book.getAuthor()), () -> assertEquals("Sayings of the Century", book.getTitle()), () -> assertEquals(8.95, book.getPrice()) ); }
3_7. JSONPath 옵션을 사용하여 JSON 데이터에서 경로 리스트를 추출
Option.AS_PATH_LIST 옵션을 사용하여 JSON 데이터에서 모든 경로 리스트를 추출하고 이를 검증합니다.@DisplayName("getPathList_JSON 객체에서 경로 리스트를 조회") @Test void testGetPathList() { // Given // Option.AS_PATH_LIST는 JsonPath 표현식에 매칭되는 모든 경로를 리스트의 형태로 반환 Configuration conf = Configuration.builder() .options(Option.AS_PATH_LIST) .build(); String jsonPath = "$..author"; List<String> expectedPathList = Arrays.asList( "$['store']['book'][0]['author']", "$['store']['book'][1]['author']", "$['store']['book'][2]['author']", "$['store']['book'][3]['author']"); // When // 경로 리스트를 추출 List<String> pathList = JsonPath .using(conf) .parse(json) .read(jsonPath); log.debug("pathList : {}", pathList); // Then assertAll( () -> assertFalse(pathList.isEmpty()), () -> assertArrayEquals(expectedPathList.toArray(), pathList.toArray()) ); }
JsonPath - https://github.com/json-path/JsonPath
소스 코드는 Github Repository - https://github.com/tychejin1218/blog/tree/main/json-modules/json-path 프로젝트를 참조하세요.
반응형'Java > 기타' 카테고리의 다른 글
[Java] MapStruct를 활용한 객체 변환 (0) 2024.09.21 [Java] ModelMapper를 활용한 객체 변환 (0) 2024.08.17 [Java] DOM4J를 이용한 XML(문자열, 파일) 파싱 (0) 2021.09.23 [Java] JDOM2을 이용한 XML(문자열, 파일) 파싱 (0) 2021.09.23 [JAVA] HttpURLConnection을 활용한 HTTP 요청 (0) 2021.07.04