package com.eactive.eai.util; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; // TOUSE // kbbank 어댑터에서 업무데이터의 암호화 필드에 대한 암복호화시 // 해당 필드에 대한 get/set 을 수행 public class JsonPathUtil { private JsonPathUtil() { } private static final ObjectMapper objectMapper = new ObjectMapper(); // 특정 경로의 값을 설정하는 함수 public static String setValueAtPath(String jsonString, String path, String newValue, boolean isPretty) { try { // JSON 문자열을 JsonNode 객체로 파싱 JsonNode rootNode = objectMapper.readTree(jsonString); // 경로에 해당하는 부모 노드를 가져옴 JsonNode parentNode = getParentNode(rootNode, getParentPath(path)); // 경로의 마지막 노드 이름 또는 배열 인덱스 추출 String fieldNameOrIndex = getFieldName(path); // 배열 또는 객체에서 값을 설정 if (parentNode.isArray()) { ((ArrayNode) parentNode).set(Integer.parseInt(fieldNameOrIndex), objectMapper.convertValue(newValue, JsonNode.class)); } else if (parentNode.isObject()) { ((ObjectNode) parentNode).put(fieldNameOrIndex, newValue); } // 수정된 JSON 문자열 반환 if(isPretty) return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(rootNode); else return objectMapper.writeValueAsString(rootNode); } catch (Exception e) { e.printStackTrace(); return null; } } // 특정 경로의 값을 가져오는 함수 public static String getValueAtPath(String jsonString, String path) { try { // JSON 문자열을 JsonNode 객체로 파싱 JsonNode rootNode = objectMapper.readTree(jsonString); // 경로에 해당하는 노드의 값을 반환 JsonNode resultNode = getNodeAtPath(rootNode, path); return resultNode != null ? resultNode.asText() : null; } catch (Exception e) { e.printStackTrace(); return null; } } // 경로에서 부모 경로를 추출하는 유틸리티 함수 private static String getParentPath(String path) { int lastSlashIndex = path.lastIndexOf('/'); return lastSlashIndex == 0 ? "/" : path.substring(0, lastSlashIndex); } // 경로에서 필드 이름 또는 배열 인덱스를 추출하는 유틸리티 함수 private static String getFieldName(String path) { int lastSlashIndex = path.lastIndexOf('/'); return path.substring(lastSlashIndex + 1); } // 특정 경로에 해당하는 부모 노드를 가져오는 유틸리티 함수 private static JsonNode getParentNode(JsonNode rootNode, String parentPath) { return getNodeAtPath(rootNode, parentPath); } // 특정 경로에 해당하는 노드를 가져오는 유틸리티 함수 private static JsonNode getNodeAtPath(JsonNode rootNode, String path) { String[] tokens = path.split("/"); JsonNode currentNode = rootNode; for (String token : tokens) { if (token.isEmpty()) continue; if (token.matches("\\d+")) { // 배열 인덱스 처리 currentNode = currentNode.get(Integer.parseInt(token)); } else { // 객체 필드 처리 currentNode = currentNode.get(token); } if (currentNode == null) { return null; // 경로가 존재하지 않음 } } return currentNode; } public static void main(String[] args) { String jsonString = "{ \"person\": { \"name\": \"John\", \"age\": 30, \"groups\": [ { \"id\": 1, \"name\": \"Group A\" }, { \"id\": 2, \"name\": \"Group B\" }, { \"id\": 3, \"name\": \"Group C\" } ] } }"; System.out.println("Source JSON: \n" + jsonString); // 경로를 사용하여 값 가져오기 (반복되는 그룹 포함) String getPath = "/person/groups/1/name"; String secondGroupName = getValueAtPath(jsonString, getPath); System.out.println("getPath: " + getPath + " -> " + secondGroupName); // 경로를 사용하여 값 설정하기 (반복되는 그룹 포함) 및 Pretty 출력 String putPath = "/person/groups/2/name"; String updatedJsonString = setValueAtPath(jsonString, putPath, "Group Z", true); System.out.println("putPath: " + putPath); System.out.println("Updated JSON (Pretty): \n" + updatedJsonString); getPath = "/person/name"; System.out.println("getPath: " + getPath + " -> " + getValueAtPath(jsonString, getPath)); getPath = "/person/age"; System.out.println("getPath: " + getPath + " -> " + getValueAtPath(jsonString, getPath)); } }