상세 컨텐츠

본문 제목

Jackson - ObjectMapper 사용법 (readValue, writeValue, JsonNode, ObjectNode)

Spring/JAVA

by Chan.94 2024. 12. 26. 11:23

본문

반응형

Intro

이전글에서 ObjectMapper 설정에 대해 정리하였다. 이번글에서는 ObjectMapper를 사용법에 대해 정리해보고자 한다.

 

 

Jackson - ObjectMapper Custom 설정

IntroJackson 라이브러리는 자바에서 JSON 데이터를 처리하기 위한 라이브러리다.Jackson의 ObjectMapper는 자바 객체와 JSON 데이터 사이의 직렬화와 역직렬화를 담당하는 클래스다. 직렬화(Se

fvor001.tistory.com

 


readValue() - 역직렬화

  • JSON 문자열 또는 파일 등의 데이터를 Java 객체로 변환한다.
  • Jackson은 리플렉션(Reflection)을 사용하여 객체를 생성하기 때문에 역직렬화를 위해서는 기본생성자가 반드시 필요하다.
<T> T readValue(String content, Class<T> valueType)
<T> T readValue(File src, Class<T> valueType)
<T> T readValue(InputStream src, Class<T> valueType)
<T> T readValue(byte[] src, Class<T> valueType)
<T> T readValue(String content, TypeReference<T> valueTypeRef)

 

제네릭 타입(List, Map 등)을 처리하려면 TypeReference를 사용해야 한다.

 

JSON → Java Object

String json = "{ \"name\": \"Dev\", \"age\": 31 }";
User user = objectMapper.readValue(json, User.class);

 

JSON Array → Java Object List

String jsonArray = "[{ \"name\": \"Dev\", \"age\": 31 }, { \"name\": \"Log\", \"age\": 30 }]";
List<User> userList = objectMapper.readValue(jsonArray, new TypeReference<List<User>>() {});

 

JSON → Java Map

String json = "{ \"name\": \"Dev\", \"age\": 31 }";
Map<String, Object> user = objectMapper.readValue(jsonArr, new TypeReference<Map<String, Object>>() {});

writeValue() - 직렬화

void writeValue(File resultFile, Object value)
void writeValue(OutputStream out, Object value)
String writeValueAsString(Object value)
byte[] writeValueAsBytes(Object value)

 

Java Object → JSON

User user = new User();
user.setName("Dev");
user.setAge(31);

String userAsString = objectMapper.writeValueAsString(user);

 

Java Object → Byte

byte[] userAsByte = objectMapper.writeValueAsBytes(user);

 


JsonNode

JsonNode는 JSON 데이터의 트리(tree) 구조를 표현하는 데 사용되며, 이를 통해 JSON 데이터를 탐색할 수 있다.

JsonNode readTree(String content)
JsonNode readTree(InputStream src)
JsonNode readTree(File src)

 

JsonNode 특징

  • JsonNode는 JSON 데이터를 트리 형태로 표현한다. JSON의 키-값 구조를 부모-자식 노드로 매핑한다.
  • 기존 노드를 수정할 수 없다.
  • get(String fieldName), path(String fieldName)을 사용하여 특정 필드의 값을 가져올 수 있다.
    찾는 필드가 없는 경우에 서로 다른 값을 리턴한다.
    get()은 실제 값이 null인지 잘못된 Node인지 확인할 수 없지만 path()를 사용하여 MissingNode인지 체크할 수 있다.
    즉, 해당 필드의 존재유무를 체크할 수 있다.
    • get() : null
    • path() : MissingNode
  • asText(), asInt(), asBoolean() 등 메서드를 통해 데이터를 특정 타입으로 변환할 수 있다.
  • isObject(), isArray(), isTextual() 등의 메서드를 통해 JSON 노드의 타입을 확인할 수 있다.
  • fields(), elements() 메서드를 통해 트리를 탐색할 수 있다.
    • fields(): 객체 노드의 모든 필드를 이터레이터로 반환
    • elements(): 배열 노드의 모든 요소를 이터레이터로 반환
  • JsonNode → JSON 변환
JsonNode rootNode = objectMapper.readTree(sJson);

//JSON 문자열로 변환하여 리턴
log.info("toString : {}", rootNode.toString ());
log.info("toPrettyString : {}", rootNode.toPrettyString()); //사용자가 읽기 쉽도록, 들여쓰기 등을 적용

 

JsonNode Example

JSON String

{
    "user": {
        "name": "DevLog",
        "age": 31,
        "address": {
            "city": "Seoul",
            "zipCode": "12345"
        }
    },
    "isActive": true,
    "roles": ["admin", "editor", "viewer"],
    "settings": {
        "notifications": {
            "email": true,
            "sms": false
        },
        "theme": "dark"
    }
}

Example

try {
    log.info("Input JSON : {}", sJson);
    
    // JSON 문자열을 JsonNode로 변환
    JsonNode rootNode = objectMapper.readTree(sJson);
    
    // 데이터 추출
    JsonNode userNode = rootNode.get("user");
    String name = userNode.get("name").asText();
    int age = userNode.get("age").asInt();
    String city = userNode.get("address").get("city").asText();
    String zipCode = userNode.get("address").get("zipCode").asText();

    // JSON에 없는 값 읽기
    // 리턴되는 객체가 MissingNode인지 체크하기 위해서 'isMissingNode()' 메소드를 사용할 수 있다.
    JsonNode userEmailByGet = userNode.get("email");        //null
    JsonNode userEmailByPath = userNode.path("email");      //userEmailByPath.getClass() : class com.fasterxml.jackson.databind.node.MissingNode
    if (userEmailByPath.isMissingNode()) {
        log.info("{} 속성을 찾을수 없습니다.", "email");
    }
    
    boolean isActive = rootNode.get("isActive").asBoolean();
    
    // roles 배열 처리
    JsonNode rolesNode = rootNode.get("roles");
    log.info("Roles:");
    for (JsonNode roleNode : rolesNode) {
        log.info("  - {}", roleNode.asText());
    }

    // settings.notifications 처리
    JsonNode settingsNode = rootNode.get("settings");
    JsonNode notificationsNode = settingsNode.get("notifications");
    boolean emailNotifications = notificationsNode.get("email").asBoolean();
    boolean smsNotifications = notificationsNode.get("sms").asBoolean();
    String theme = settingsNode.get("theme").asText();
    
    // 결과 출력
    log.info("===User Info===");
    log.info("  Name: {}", name);
    log.info("  Age: {}", age);
    log.info("  City: {}", city);
    log.info("  Zip Code: {}", zipCode);
    log.info("  Is Active: {}", isActive);
    log.info("");
    log.info("  get, path Method Compare");
    log.info("    userEmailByGet: {}", userEmailByGet);
    log.info("    userEmailByPath: {}", userEmailByPath.getClass());
    log.info("");
    log.info("===Notification Settings===");
    log.info("  Email: {}", emailNotifications);
    log.info("  SMS: {}", smsNotifications);
    log.info("  Theme: {}", theme);
    
} catch (JsonProcessingException e) {
    
}

 

output

Input JSON : { "user": { "name": "DevLog", "age": 31, "address": { "city": "Seoul", "zipCode": "12345" } }, "isActive": true, "roles": ["admin", "editor", "viewer"], "settings": { "notifications": { "email": true, "sms": false }, "theme": "dark" } }
email 속성을 찾을수 없습니다.
Roles:
  - admin
  - editor
  - viewer
===User Info===
  Name: DevLog
  Age: 31
  City: Seoul
  Zip Code: 12345
  Is Active: true

  get, path Method Compare
    userEmailByGet: null
    userEmailByPath: class com.fasterxml.jackson.databind.node.MissingNode

===Notification Settings===
  Email: true
  SMS: false
  Theme: dark

 

JsonNode는 수정할 수 없다. 추가하거나 수정이 필요하면 ObjectNode를 사용해야 한다.

 


ObjectNode

  • 추가, 수정할 수 있는 객체를 생성하기 위해 기존의 JsonNode객체는 ObjectNode 객체로 캐스팅하여 사용한다.
  • 새로운 객체는 createObjectNode() 메서드를 사용한다.

ObjectNode Example

String result;
try {
    log.info("Input JSON : {}", sJson);
    
    // JSON 문자열을 JsonNode로 변환
    JsonNode rootNode = objectMapper.readTree(sJson);
    // ObjectNode Casting
    ObjectNode userNode = (ObjectNode) rootNode.get("user");
    userNode.put("email", "test@naver.com");
    
    //JSON 문자열로 변환하여 리턴
    result = rootNode.toPrettyString(); 
    log.info("result : {}", result);
    
} catch (JsonProcessingException e) {

}

 

기존 JSON에 email을 추가하여 반환하는 예시이다.

 

output

result : {
  "user" : {
    "name" : "DevLog",
    "age" : 31,
    "address" : {
      "city" : "Seoul",
      "zipCode" : "12345"
    },
    "email" : "test@naver.com"
  },
  "isActive" : true,
  "roles" : [ "admin", "editor", "viewer" ],
  "settings" : {
    "notifications" : {
      "email" : true,
      "sms" : false
    },
    "theme" : "dark"
  }
}
반응형

관련글 더보기

댓글 영역

>