반응형

dependency

  • maven
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13.0</version>
</dependency>
  • gradle
dependencies {
    ...
    implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.0'
}

기본 예제

@Data
public class TodoResponse {
    @JsonProperty("status")
    private Status status;
    @JsonProperty("title")
    private String title;
    @JsonProperty("todo_items")
    private List<TodoItem> todoItems;

    @Data
    public static class Status {
        @JsonProperty("code")
        private String code;
    }

    @Data
    public static class TodoItem {
        @JsonProperty("contents")
        private String contents;
        @JsonProperty("order")
        private Integer order;
    }
}
public class JacksonTest {
    @Test
    public void objectToJson() throws JsonProcessingException {
        TodoResponse.Status status = new TodoResponse.Status();
        status.setCode("SUCCESS");

        TodoResponse.TodoItem item1 = new TodoResponse.TodoItem();
        item1.setContents("Hello 1");
        item1.setOrder(1);

        TodoResponse.TodoItem item2 = new TodoResponse.TodoItem();
        item2.setContents("Hello 2");
        item2.setOrder(2);

        TodoResponse response = new TodoResponse();
        response.setStatus(status);
        response.setTitle("Hello World");
        response.setTodoItems(Arrays.asList(item1, item2));

        ObjectMapper mapper = new ObjectMapper();
        String json = mapper.writeValueAsString(response);

        assertEquals("{\"status\":{\"code\":\"SUCCESS\"},\"title\":\"Hello World\",\"todo_items\":[{\"contents\":\"Hello 1\",\"order\":1},{\"contents\":\"Hello 2\",\"order\":2}]}", json);
    }

    @Test
    public void jsonToObject() throws JsonProcessingException {
        String json = "{\"status\":{\"code\":\"SUCCESS\"},\"title\":\"Hello World\",\"todo_items\":[{\"contents\":\"Hello 1\",\"order\":1},{\"contents\":\"Hello 2\",\"order\":2}]}";

        ObjectMapper mapper = new ObjectMapper();
        TodoResponse response = mapper.readValue(json, TodoResponse.class);

        assertEquals("SUCCESS", response.getStatus().getCode());
        assertEquals("Hello World", response.getTitle());
        assertEquals("Hello 1", response.getTodoItems().get(0).getContents());
        assertEquals("Hello 2", response.getTodoItems().get(1).getContents());
    }

    @Test
    public void jsonToObjectFromSpecificField() throws JsonProcessingException {
        String json = "{\"status\":{\"code\":\"SUCCESS\"},\"title\":\"Hello World\",\"todo_items\":[{\"contents\":\"Hello 1\",\"order\":1},{\"contents\":\"Hello 2\",\"order\":2}]}";

        ObjectMapper mapper = new ObjectMapper();
        JsonNode node = mapper.readTree(json).findPath("status");
        TodoResponse.Status status = mapper.readValue(node.toString(), TodoResponse.Status.class);

        assertEquals("SUCCESS", status.getCode());
    }

    @Test
    public void jsonToListFromSpecificField() throws JsonProcessingException {
        String json = "{\"status\":{\"code\":\"SUCCESS\"},\"title\":\"Hello World\",\"todo_items\":[{\"contents\":\"Hello 1\",\"order\":1},{\"contents\":\"Hello 2\",\"order\":2}]}";

        ObjectMapper mapper = new ObjectMapper();
        JsonNode node = mapper.readTree(json).findPath("todo_items");
        CollectionType collectionType = mapper.getTypeFactory().constructCollectionType(List.class, TodoResponse.TodoItem.class);
        List<TodoResponse.TodoItem> items = mapper.readValue(node.toString(), collectionType);

        assertEquals("Hello 1", items.get(0).getContents());
        assertEquals("Hello 2", items.get(1).getContents());
    }
}

Enum Handling

public class JacksonEnumBasicTest {
    @RequiredArgsConstructor
    @Getter
    public enum Status {
        SUCCESS("AA01", "성공"),
        FAIL("AA02", "실패");

        private final String code;
        private final String desc;
    }

    @Test
    public void testEnum() throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        String json = mapper.writeValueAsString(Status.SUCCESS);
        Status status = mapper.readValue(json, Status.class);

        assertEquals("\"SUCCESS\"", json);
        assertEquals(Status.SUCCESS, status);
    }
}
public class JacksonEnumJsonFormatTest {
    @JsonFormat(shape = JsonFormat.Shape.OBJECT)
    @RequiredArgsConstructor
    @Getter
    public enum Status {
        SUCCESS("AA01", "성공"),
        FAIL("AA02", "실패");

        private final String code;
        private final String desc;

        @JsonCreator
        public static Status of(@JsonProperty("code") String code, @JsonProperty("desc") String desc) {
            return Arrays.stream(Status.values())
                .filter(it -> it.getCode().equals(code))
                .filter(it -> it.getDesc().equals(desc))
                .findFirst()
                .orElse(null);
        }
    }

    @Test
    public void testEnum() throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        String json = mapper.writeValueAsString(Status.SUCCESS);
        Status status = mapper.readValue(json, Status.class);

        assertEquals("{\"code\":\"AA01\",\"desc\":\"성공\"}", json);
        assertEquals(Status.SUCCESS, status);
    }
}
public class JacksonEnumJsonPropertyTest {
    @RequiredArgsConstructor
    @Getter
    public enum Status {
        @JsonProperty("STATUS_SUCCESS")
        SUCCESS("AA01", "성공"),
        @JsonProperty("STATUS_FAIL")
        FAIL("AA02", "실패");

        private final String code;
        private final String desc;
    }

    @Test
    public void testEnum() throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        String json = mapper.writeValueAsString(Status.SUCCESS);
        Status status = mapper.readValue(json, Status.class);

        assertEquals("\"STATUS_SUCCESS\"", json);
        assertEquals(Status.SUCCESS, status);
    }
}
public class JacksonEnumJsonValueFieldTest {
    @RequiredArgsConstructor
    @Getter
    public enum Status {
        SUCCESS("AA01", "성공"),
        FAIL("AA02", "실패");

        @JsonValue
        private final String code;
        private final String desc;
    }

    @Test
    public void testEnum() throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        String json = mapper.writeValueAsString(Status.SUCCESS);
        Status status = mapper.readValue(json, Status.class);

        assertEquals("\"AA01\"", json);
        assertEquals(Status.SUCCESS, status);
    }
}
public class JacksonEnumJsonValueMethodTest {
    @RequiredArgsConstructor
    @Getter
    public enum Status {
        SUCCESS("AA01", "성공"),
        FAIL("AA02", "실패");

        private final String code;
        private final String desc;

        @JsonValue
        public String getValue() {
            return code + "-" + desc;
        }
    }

    @Test
    public void testEnum() throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        String json = mapper.writeValueAsString(Status.SUCCESS);
        Status status = mapper.readValue(json, Status.class);

        assertEquals("\"AA01-성공\"", json);
        assertEquals(Status.SUCCESS, status);
    }
}
public class JacksonEnumSerializerAndDeserializerTest {
    @JsonSerialize(using = StatusSerializer.class)
    @JsonDeserialize(using = StatusDeserializer.class)
    @RequiredArgsConstructor
    @Getter
    public enum Status {
        SUCCESS("AA01", "성공"),
        FAIL("AA02", "실패");

        private final String code;
        private final String desc;
    }

    public static class StatusSerializer extends StdSerializer<Status> {
        public StatusSerializer() {
            super(Status.class);
        }

        @Override
        public void serialize(Status value, JsonGenerator gen, SerializerProvider provider) throws IOException {
            gen.writeStartObject();
            gen.writeFieldName("code");
            gen.writeString(value.getCode());
            gen.writeFieldName("desc");
            gen.writeString(value.getDesc());
            gen.writeEndObject();
        }
    }

    public static class StatusDeserializer extends StdDeserializer<Status> {
        public StatusDeserializer() {
            super(Status.class);
        }

        @Override
        public Status deserialize(JsonParser parser, DeserializationContext context) throws IOException {
            JsonNode node = parser.getCodec().readTree(parser);

            String code = node.get("code").asText();
            String desc = node.get("desc").asText();

            return Arrays.stream(Status.values())
                .filter(it -> it.getCode().equals(code))
                .filter(it -> it.getDesc().equals(desc))
                .findFirst()
                .orElse(null);
        }
    }

    @Test
    public void testEnum() throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        String json = mapper.writeValueAsString(Status.SUCCESS);
        Status status = mapper.readValue(json, Status.class);

        assertEquals("{\"code\":\"AA01\",\"desc\":\"성공\"}", json);
        assertEquals(Status.SUCCESS, status);
    }
}

configure

ObjectMapper mapper = new ObjectMapper();

// json에 있는 필드가 object에 없을 경우 발생시키는 오류를 비활성화
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

// 필드명을 감싸는 문자로 "뿐만 아니라 '도 허용. ex) {'key': "value"}
mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);

// 필드명을 감싸는 문자가 없는 것 허용. ex) {key: "value"}
mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);

// 끝에 ,가 붙는 것 허용. ex) {"key": "value",}
mapper.configure(JsonParser.Feature.ALLOW_TRAILING_COMMA, true);

// json 내용에 주석이 포함되어 있는 것 허용.
mapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);

참고

반응형

'Development > Java' 카테고리의 다른 글

[Java] JDK 버전별 신규 기능  (0) 2019.04.21
[Java] XML 파싱  (0) 2019.03.20
[Java] HTML 파싱  (0) 2019.03.20
[Java] Garbage Collector  (0) 2018.07.24
[Java] JDK 설치  (0) 2018.07.22

+ Recent posts