어제 오늘 내일

[Java/Jackson] JsonNode 생성, 읽기, 쓰기, 수정 예제 본문

IT/Java

[Java/Jackson] JsonNode 생성, 읽기, 쓰기, 수정 예제

hi.anna 2021. 9. 6. 00:48

Jackson의 JsonNode를 다루는 방법을 정리하였습니다.

 

1
  1. JsonNode 생성하기
    1. JsonNode 생성하기
    2. ArrayNode 생성하기
    3. JSON 문자열로 JsonNode 생성하기
    4. Java Object로 JsonNode 생성하기
    5. Map으로 JsonNode 생성하기
  2. JsonNode 변환하기
    1. JsonNode를 JSON 문자열로 변환하기
    2. JsonNode를 Java Object로 변환하기
  3. JsonNode 읽기
    1. Field 읽기 - get(), path(), at()
    2. get() vs path()
    3. null 체크하기
  4. JsonNode 쓰기(추가)
    1. Primitive Type, 새로운 Node 추가
    2. ArrayNode에 값 추가

 

1. JsonNode 생성하기

1.1. JsonNode 생성하기

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

public class CreateJsonNode {
    public static void main(String[] args) {

        // ObjectMapper 생성
        ObjectMapper mapper = new ObjectMapper();

        // JsonNode 생성
        JsonNode jsonNode = mapper.createObjectNode();

    }
}

 

1.2. ArrayNode 생성하기

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;

public class CreateArrayNode {
    public static void main(String[] args) {

        // ObjectMapper 생성
        ObjectMapper mapper = new ObjectMapper();

        // ArrayNode 생성
        ArrayNode arrayNode = mapper.createArrayNode();

    }
}


1.3. JSON 문자열로 JsonNode 생성하기

[Java/Jackson] Json 문자열을 JsonNode로 변환하기

 

1.4. Java Object로 JsonNode 생성하기

[Java/Jackson] Java Object를 JsonNode로 변환하기

 

1.5. Map으로 JsonNode 생성하기

[Java/Jackson] Map을 JsonNode로 변환하기

 

2. JsonNode 변환하기

2.1. JsonNode를 JSON 문자열로 변환하기

[Java/Jackson] JsonNode를 JSON 문자열로 변환하기

 

2.2. JsonNode를 Java Object로 변환하기

[Java/Jackson] JsonNode를 Object로 변환하기

 

3. JsonNode 읽기

"JsonNode 읽기" 예제는 모두 다음의 "lecture.json" 파일을 읽습니다.

  lecture.json  

{
    "id": 1,
    "title": "Java",
    "professor": {
        "id": "P1",
        "name": "Kim"
    },
    "students": [
        {
            "id": "S1",
            "name": "Anna"
        },
        {
            "id": "S2",
            "name": "Brian"
        }
    ],
    "textbook": null
}

 

3.1. Field 읽기 - get(), path(), at()

  코드  

import java.io.File;
import java.io.IOException;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

public class ReadJsonField {
    public static void main(String[] args) throws JsonProcessingException, IOException {

        // jackson objectmapper 객체 생성
        ObjectMapper objectMapper = new ObjectMapper();

        // JsonNode 생성 (readValue)
        JsonNode jsonNode = objectMapper.readTree(new File("c:\\json\\lecture.json"));

        // JsonNode 읽기
        readJsonNodeWithGet(jsonNode);
        readJsonNodeWithPath(jsonNode);
        readJsonNodeWithAt(jsonNode);

    }

    public static void readJsonNodeWithGet(JsonNode jsonNode) {
        int lectureId = jsonNode.get("id").asInt();
        String lectureName = jsonNode.get("title").asText();
        String professorName = jsonNode.get("professor").get("name").asText();
        String studentName1 = jsonNode.get("students").get(0).get("name").asText();
        String studentName2 = jsonNode.get("students").get(1).get("name").asText();

        System.out.println("----- get() -----");
        System.out.println(lectureId); // 1
        System.out.println(lectureName); // Java
        System.out.println(professorName); // Kim
        System.out.println(studentName1); // Anna
        System.out.println(studentName2); // Brian
    }

    public static void readJsonNodeWithPath(JsonNode jsonNode) {
        int lectureId = jsonNode.path("id").asInt();
        String lectureName = jsonNode.path("title").asText();
        String professorName = jsonNode.path("professor").path("name").asText();
        String studentName1 = jsonNode.path("students").path(0).path("name").asText();
        String studentName2 = jsonNode.path("students").path(1).path("name").asText();

        System.out.println("----- path() -----");
        System.out.println(lectureId); // 1
        System.out.println(lectureName); // Java
        System.out.println(professorName); // Kim
        System.out.println(studentName1); // Anna
        System.out.println(studentName2); // Brian
    }

    public static void readJsonNodeWithAt(JsonNode jsonNode) {
        int lectureId = jsonNode.at("/id").asInt();
        String lectureName = jsonNode.at("/title").asText();
        String professorName = jsonNode.at("/professor/name").asText();
        String studentName1 = jsonNode.at("/students/0/name").asText();
        String studentName2 = jsonNode.at("/students/1/name").asText();

        System.out.println("----- at() -----");
        System.out.println(lectureId); // 1
        System.out.println(lectureName); // Java
        System.out.println(professorName); // Kim
        System.out.println(studentName1); // Anna
        System.out.println(studentName2); // Brian
    }
}

  결과  

----- get() -----
1
Java
Kim
Anna
Brian
----- path() -----
1
Java
Kim
Anna
Brian
----- at() -----
1
Java
Kim
Anna
Brian

 

다음의 3가지 메소드를 사용하여

JsonNode의 필드의 값을 읽을 수 있습니다.

  • get()
  • path()
  • at()

 

3.2. get() vs path()

3.1의 예제에서 get()과 path()는 거의 차이가 없어보입니다.

이 두 가지 메소드는,

찾는 필드가 없는 경우에 서로 다른 값을 리턴합니다.

 

  예제  

import java.io.File;
import java.io.IOException;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

public class DiffPathAndAt {
    public static void main(String[] args) throws JsonProcessingException, IOException {

        // jackson objectmapper 객체 생성
        ObjectMapper objectMapper = new ObjectMapper();

        // JsonNode 생성 (readValue)
        JsonNode jsonNode = objectMapper.readTree(new File("c:\\json\\lecture.json"));

        // JsonNode 읽기
        missingJsonNodeWithGet(jsonNode);
        missingJsonNodeWithPath(jsonNode);
    }

    private static void missingJsonNodeWithGet(JsonNode jsonNode) {
        JsonNode classRoomNode = jsonNode.get("classRoom");

        System.out.println("----- get() -----");
        System.out.println(classRoomNode); // null
    }

    private static void missingJsonNodeWithPath(JsonNode jsonNode) {
        JsonNode classRoomNode = jsonNode.path("classRoom");

        System.out.println("----- path() -----");
        System.out.println(classRoomNode.getClass()); // class com.fasterxml.jackson.databind.node.MissingNode

        // check missing node
        if (classRoomNode.isMissingNode()) {
            System.out.println("노드를 찾을 수 없습니다.");
        }
    }

}

  결과  

----- get() -----
null
----- path() -----
class com.fasterxml.jackson.databind.node.MissingNode
노드를 찾을 수 없습니다.

이 예제에서는 'lecture.json' 파일의 'classroom' 필드를 읽으려고 시도합니다.

그러나, lecture.json 파일에는 'classroom' 필드가 존재하지 않습니다.

찾는 필드가 존재하지 않을 경우

  • get() 메소드는
    null을 리턴합니다.
  • path() 메소드는
    MissingNode 객체를 리턴합니다.
    리턴되는 객체가 MissingNode인지 체크하기 위해서 'isMissingNode()' 메소드를 사용할 수 있습니다.

 

3.3. null 체크하기

  예제  

import java.io.File;
import java.io.IOException;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

public class CheckNullValue {
    public static void main(String[] args) throws JsonProcessingException, IOException {

        // jackson objectmapper 객체 생성
        ObjectMapper objectMapper = new ObjectMapper();

        // JsonNode 생성 (readValue)
        JsonNode jsonNode = objectMapper.readTree(new File("c:\\json\\lecture.json"));

        // 특정 field의 값이 null인 경우
        checkNullValue(jsonNode);

        // 특정 field가 없는 경우
        checkMissingNode(jsonNode);
    }

    private static void checkNullValue(JsonNode jsonNode) {
        JsonNode textbookNode = jsonNode.path("textbook");

        System.out.println("----- 특정 field의 값이 null인 경우 -----");
        System.out.println(textbookNode); // null
        System.out.println(textbookNode.isNull()); // true
    }

    private static void checkMissingNode(JsonNode jsonNode) {
        JsonNode classroomNode = jsonNode.path("classroom");

        System.out.println("----- 특정 field가 없는 경우 -----");
        System.out.println(classroomNode); //
        System.out.println(classroomNode.getClass()); // class com.fasterxml.jackson.databind.node.MissingNode
        System.out.println(classroomNode.isMissingNode()); // true
    }
}

  결과  

----- 특정 field의 값이 null인 경우 -----
null
true
----- 특정 field가 없는 경우 -----

class com.fasterxml.jackson.databind.node.MissingNode
true

 

checkNullValue()

특정 필드의 값이 null인 경우를 체크하는 예제입니다.

( 'lecture.json' 파일에서, 'textbook' 필드의 값은 null 입니다. )

path() 메소드를 사용하여 필드를 탐색했을 때,

특정 필드의 값이 null이면, 

path() 메소드는 값 그대로 null을 리턴합니다.

이 값이 null인지 체크하기 위해서 'isNull()' 메소드를 사용할 수 있습니다.

 

checkMissingNode()

특정 필드가 아예 존재하지 않는 경우를 체크하는 예제입니다.

( 'lecture.json' 파일에, 'classroom' 필드는 존재하지 않습니다. )

path() 메소드를 사용하여 필드를 탐색했을 때,

해당 필드가 존재하지 않으면,

path() 메소드는 MissingNode 객체를 리턴합니다.

path() 메소드가 리턴하는 값이 MissingNode 객체인지 체크하기 위해서

'isMissingNode()' 메소드를 사용할 수 있습니다.

 

4. JsonNode 쓰기(추가)
4. 1. Primitive Type, 새로운 Node 추가

import java.io.File;
import java.io.IOException;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;

public class AddNode {
    public static void main(String[] args) throws JsonProcessingException, IOException {
        // ObjectMapper 생성
        ObjectMapper mapper = new ObjectMapper();

        addPrimitiveType(mapper);
        addNewNode(mapper);

    }

    private static void addPrimitiveType(ObjectMapper mapper) throws JsonProcessingException, IOException {
        // lecture JSON 읽기
        ObjectNode lectureNode = (ObjectNode) mapper.readTree(new File("c:\\json\\lecture.json"));

        // primitive type 추가
        lectureNode.put("classroom", 101);

        // 결과 출력
        System.out.println("----- classroom 노드 추가 -----");
        System.out.println(lectureNode);
    }

    private static void addNewNode(ObjectMapper mapper) throws JsonProcessingException, IOException {
        // lecture JSON 읽기
        ObjectNode lectureNode = (ObjectNode) mapper.readTree(new File("c:\\json\\lecture.json"));

        // ObjectNode 생성
        ObjectNode contact = mapper.createObjectNode();
        contact.put("tel", "010-1111-1111");
        contact.put("email", "aa@mail.com");

        lectureNode.set("contact", contact);

        // 결과출력
        System.out.println("----- contact 노드 추가 -----");
        System.out.println(lectureNode);
    }
}

 

JsonNode는 Immutable 입니다.

따라서, JsonNode에 값을 추가하거나 수정할 수 없습니다.

따라서, JsonNode를 수정하기 위해서는 JsonNode 대신 ObjectNode 객체를 사용합니다.

 

ObjectNode lectureNode = (ObjectNode) mapper.readTree(..);
ObjectNode contact = mapper.createObjectNode();

추가, 수정 할수 있는 객체를 생성하기 위해

기존의 JsonNode객체는 ObjectNode 객체로 타입 캐스팅하고,

새로운 객체는 createObjectNode() 메소드를 사용하여, ObjectNode 객체를 생성하였습니다.

 

 

addPrimitiveType()

primitive type을 JsonNode에 추가하는 예제입니다.

lectureNode.put("classroom", 101);

put() 메소드를 사용하여 값을 추가하였습니다.

 

 

addNewNode()

새로운 JsonNode를 생성하여 추가하는 예제입니다.

lectureNode.set("contact", contact);

set() 메소드를 사용하여 새로운 노드를 추가하였습니다.

 

 

4. 2. ArrayNode에 값 추가

  예제  

import java.util.Arrays;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

public class AddArrayNode {
    public static void main(String[] args) {

        // ObjectMapper 생성
        ObjectMapper mapper = new ObjectMapper();

        arrayNodeForPrimitiveType(mapper);
        arrayNodeForJsonNode(mapper);
    }

    private static void arrayNodeForPrimitiveType(ObjectMapper mapper) {
        // ObjectNode 생성
        ObjectNode objectNode = mapper.createObjectNode();

        // ArrayNode 생성
        ArrayNode arr = mapper.createArrayNode();
        // ArrayNode에 primitive type element 추가
        arr.add("a");
        arr.add("b");
        arr.add("c");

        // ObjectNode에 ArrayNode 추가
        objectNode.set("alphabet", arr);

        // 결과 출력
        System.out.println("----- ArrayNode(Primitive Type) -----");
        System.out.println(objectNode);
    }

    private static void arrayNodeForJsonNode(ObjectMapper mapper) {
        // ObjectNode 생성
        ObjectNode objectNode = mapper.createObjectNode();

        // Array에 들어갈 Elements 생성
        ObjectNode element1 = mapper.createObjectNode();
        element1.put("id", 1);
        element1.put("name", "Anna");

        ObjectNode element2 = mapper.createObjectNode();
        element2.put("id", 2);
        element2.put("name", "Brian");

        ObjectNode element3 = mapper.createObjectNode();
        element3.put("id", 3);
        element3.put("name", "Sam");

        // ArrayNode 생성
        ArrayNode students = mapper.createArrayNode();
        // ArrayNode에 Elements 추가
        students.add(element1);
        students.addAll(Arrays.asList(element2, element3));

        // ObjectNode에 ArrayNode 추가
        objectNode.set("students", students);

        // 결과 출력
        System.out.println("----- ArrayNode(JsonNode) -----");
        System.out.println(objectNode);
    }
}

  결과  

----- ArrayNode(Primitive Type) -----
{"alphabet":["a","b","c"]}
----- ArrayNode(JsonNode) -----
{"students":[{"id":1,"name":"Anna"},{"id":2,"name":"Brian"},{"id":3,"name":"Sam"}]}

arrayNodeForPrimitiveType()

ArrayNode를 생성하고, 여기에 primitive type 값을 추가하는 예제입니다.

 

arrayNodeForJsonNode()

ArrayNode를 생성하고, 여기에 JsonNode(ObjectNode)를 생성하여 추가하는 예제입니다.

한꺼번여 여러개의 Node를 추가하기 위해

addAll() 메소드를 사용할 수 있습니다.

 

 

반응형
Comments