Skip to content

Latest commit

ย 

History

History
406 lines (273 loc) ยท 14.5 KB

jackson.md

File metadata and controls

406 lines (273 loc) ยท 14.5 KB

๋ชฉ์ฐจ



Jackson ์ดํ•ดํ•˜๊ธฐ - ์‚ฌ์šฉ ๋ฐฉ๋ฒ•๊ณผ ๋™์ž‘ ๋ฐฉ์‹

API ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„๋ฅผ ๋งŒ๋“ค ๋•Œ ๋น ์งˆ ์ˆ˜ ์—†๋Š” ๋ถ€๋ถ„์ด ๊ฐ์ฒด์™€ JSON๊ฐ„์˜ ๋ณ€ํ™˜์ด๋‹ค.

์ด๋ฅผ ๋ณดํ†ต ์ง๋ ฌํ™” (๊ฐ์ฒด -> JSON), ์—ญ์ง๋ ฌํ™” (JSON -> ๊ฐ์ฒด)๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

์ด๋ฒˆ ๊ธ€์€ Java๋‚ด ๋ณดํŽธ์ ์œผ๋กœ ๋งŽ์ด ์‚ฌ์šฉ๋˜๋Š” JSON ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ Jackson์˜ ๋™์ž‘ ๋ฐฉ์‹๊ณผ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณธ๋‹ค.

์‚ฌ์šฉ ๋ฐฉ๋ฒ•๋ง๊ณ  ๋™์ž‘ ๋ฐฉ์‹์„ ์•Œ๊ณ  ์‹ถ์œผ์‹  ๋…์ž๋ผ๋ฉด ๋ฐ”๋กœ ๋ถ€๋ถ„๋ถ€ํ„ฐ ๋ณด๋Š” ๊ฒƒ์„ ์ถ”์ฒœํ•œ๋‹ค.


Jackson has been known as "the Java JSON library" or "the best JSON parser for Java". Or simply as "JSON for Java".

Jackson ๊ณต์‹ ์ €์žฅ์†Œ์— ์ ํ˜€์žˆ๋Š” ๋ฌธ๊ตฌ๋กœ Jackson์˜ ์ด๋ฆ„์€ ๊ฐ„๋‹จํžˆ "JSON for Java"์˜ ์˜๋ฏธ๋ผ๊ณ ํ•œ๋‹ค.


Jackson ์˜์กด์„ฑ

Jackson์„ ์‚ฌ์šฉํ•˜๊ณ ์žํ•˜๋ฉด jackson์˜ databind ์˜์กด์„ฑ์„ ์ถ”๊ฐ€ํ•ด์ฃผ๋ฉด๋œ๋‹ค.

implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.3'

databind ์˜์กด์„ฑ์„ ์ถ”๊ฐ€ํ•˜๋ฉด ์ž๋™์œผ๋กœ ๋‹ค์Œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋„ ์ „์˜์ ์œผ๋กœ ์ถ”๊ฐ€๋œ๋‹ค.

  • jackson-annotations
  • jackson-core

์ตœ์‹  databind ์˜์กด์„ฑ์€ Maven Repository๋ฅผ ์ฐธ๊ณ ํ•˜๋ฉด ๋œ๋‹ค.


1 ObjectMapper๋ฅผ ์ด์šฉํ•œ ์ง๋ ฌํ™”, ์—ญ์ง๋ ฌํ™”

ObjectMapper Jackson Databind ๋ชจ๋“ˆ์— ์œ„์น˜ํ•œ ๊ฐ์ฒด๋กœ์„œ, POJO ๋˜๋Š” JSON ํŠธ๋ฆฌ ๋ชจ๋ธ (JsonNode)๋ฅผ JSON๋กœ ์ฝ๊ณ  ์“ฐ๊ณ  ๋ณ€ํ™˜ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค.

๋˜ํ•œ, ์‚ฌ์šฉ์ž๊ฐ€ ์ง์ ‘ ์ง๋ ฌํ™”, ์—ญ์ง๋ ฌํ™”์— ๋Œ€ํ•œ ์ปค์Šคํ…€์„ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋„์™€์ค€๋‹ค.

ObjectMapper์˜ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์„ ์ดํ•ดํ•˜๊ธฐ์œ„ํ•ด ์•„๋ž˜์™€ ๊ฐ™์ด ๊ฐ„๋‹จํ•œ POJO๋ฅผ ์ƒ์„ฑํ•ด์ค€๋‹ค.

@Builder
@NoArgsConstructor
@AllArgsConstructor
@Setter
@Getter
public class Member {

    private String id;
    private String name;
    private int age;
}

1-1 Serialization. ๊ฐ์ฒด to JSON

๊ฐ€์žฅ ๋จผ์ € ObjectMapper๋ฅผ ์ด์šฉํ•œ ์ง๋ ฌํ™”์— ๋Œ€ํ•ด์„œ ์‚ดํŽด๋ณธ๋‹ค.


Default Serializer

ObjectMapper๋ฅผ ํ™œ์šฉํ•œ ๊ฐ์ฒด์—์„œ JSON์œผ๋กœ ์ง๋ ฌํ™”ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋Š” 3๊ฐ€์ง€ ์กด์žฌํ•œ๋‹ค.

  • writeValue()
  • writeValueAsString()
  • writeValueAsBytes()

writeValue() ์˜ˆ์‹œ

@Test
void object_to_json() throws IOException {
    // given
    ObjectMapper objectMapper = new ObjectMapper();

    // when, then
    Member member = Member.builder()
            .id("123")
            .name("binghe")
            .age(28)
            .build();
    
    objectMapper.writeValue(new FileOutputStream("data/member.json"), member);
}

์œ„์™€ ๊ฐ™์ด writeValue๋ฅผ ํ™œ์šฉํ•ด File, OutputStream, Writer๋“ฑ ๋‹ค์–‘ํ•œ ๋ฐฉ์‹์œผ๋กœ ์ง๋ ฌํ™” ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ณดํ†ต API ์„œ๋ฒ„์—์„  writeValueAsString()์„ ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉํ•œ๋‹ค.

writeValueAsString() ์˜ˆ์‹œ

@Test
void object_to_json_String() throws JsonProcessingException {
    // given
    ObjectMapper objectMapper = new ObjectMapper();

    // when
    Member member = Member.builder()
            .id("123")
            .name("binghe")
            .age(28)
            .build();
    String json = objectMapper.writeValueAsString(member);

    // then
    assertThat(json).isEqualTo("{\"id\":\"123\",\"name\":\"binghe\",\"age\":28}");
}

Custom Serializer

๋•Œ๋•Œ๋กœ Jackson์—์„œ ์ œ๊ณตํ•˜๋Š” ๋””ํดํŠธ Serializer ๋ง๊ณ , ์ƒํ™ฉ์— ๋”ฐ๋ผ ์ปค์Šคํ…€ํ•˜๊ฒŒ ๊ฐ์ฒด๋ฅผ JSON์œผ๋กœ ์ง๋ ฌํ™”ํ•ด์•ผํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด JSON์—์„œ Java ๊ฐ์ฒด์™€ ๋‹ค๋ฅธ ํ•„๋“œ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ํŠน์ • ํ•„๋“œ๋ฅผ ์™„์ „ํžˆ ์ƒ๋žตํ•ด์•ผํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋‹ค.

์•„๋ž˜ ์—์‹œ๋Š” ๊ฐ์ฒด๋‚ด ํ•„๋“œ ์ด๋ฆ„์„ JSON์œผ๋กœ ์ง๋ ฌํ™”์‹œ ๋ณ€๊ฒฝํ•ด์ฃผ๋Š” ์ปค์Šคํ…€ Serializer๋ฅผ ์ ์šฉํ•œ ์˜ˆ์‹œ์ด๋‹ค.

@Test
void object_to_json_custom_serializer() throws JsonProcessingException {
    // given
    ObjectMapper objectMapper = new ObjectMapper();
    MemberCustomSerializer memberCustomSerializer = new MemberCustomSerializer();

    SimpleModule module = new SimpleModule("MemberCustomSerializer");
    module.addSerializer(Member.class, memberCustomSerializer);

    objectMapper.registerModule(module);

    // when
    Member mem = Member.builder()
            .id("123")
            .name("binghe")
            .age(28)
            .build();
    String json = objectMapper.writeValueAsString(mem);

    // then
    assertThat(json).isEqualTo("{\"memberId\":\"123\",\"nickName\":\"binghe\",\"age\":28}");
}

private static class MemberCustomSerializer extends JsonSerializer<Member> {

    @Override
    public void serialize(Member value, JsonGenerator gen, SerializerProvider serializers) throws IOException {

        gen.writeStartObject(); // {

        gen.writeStringField("memberId", value.getId());
        gen.writeStringField("nickName", value.getName());
        gen.writeNumberField("age", value.getAge());

        gen.writeEndObject(); // }
    }
}

Module

์ปค์Šคํ…€ Serializer๋ฅผ Module์— ๋„ฃ๊ณ , Module์„ ObjectMapper์— ๋“ฑ๋กํ•ด์คŒ์œผ๋กœ์จ ์ปค์Šคํ…€ Serializer๋ฅผ ์ ์šฉํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ObjectMapper์— Module๋ฅผ ๋“ฑ๋กํ•จ์œผ๋กœ์จ ๋‹ค์–‘ํ•œ ๋ฐฉ์‹์œผ๋กœ ์ปค์Šคํ…€ ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ObjectMapper๋Š” ์—ฌ๋Ÿฌ ๊ฐœ์˜ module์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋‹ค.

  • ObjectMapper 1 : N Module. (์ •ํ™•ํžˆ๋Š” Module์„ ๋‹ค์–‘ํ•œ ObjectMapper์— ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ์–ด N : N ๊ด€๊ณ„๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๋‹ค.)
  • Module 1 : N Serializer (๋™์ผํ•˜๊ฒŒ ์ •ํ™•ํžˆ๋Š” N : N ๊ด€๊ณ„๋ผ๋„ ๋ด๋„ ๋ฌด๋ฐฉํ•˜๋‹ค.)

Jackson์€ ๋‹ค์–‘ํ•œ ์• ๋…ธํ…Œ์ด์…˜์„ ์ œ๊ณตํ•œ๋‹ค.

์œ„์™€ ๊ฐ™์ด ์ปค์Šคํ…€ Serializer๋ฅผ ๋งŒ๋“ค์–ด์„œ ์‚ฌ์šฉํ•ด๋„ ๋˜์ง€๋งŒ, ์‚ฌ์‹ค Jackson์—์„  ๋‹ค์–‘ํ•œ ์• ๋…ธํ…Œ์ด์…˜์„ ์ œ๊ณตํ•œ๋‹ค.

๊ฐ€๋Šฅํ•œ ์ด๋Ÿฌํ•œ ์• ๋…ธํ…Œ์ด์…˜์„ ํ™œ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ถ”ํ›„ ์œ ์ง€๋ณด์ˆ˜๋‚˜ ํ™•์žฅ๋ฉด์—์„œ ์šฉ์ดํ•˜๋ฏ€๋กœ ํ•„์ž๋Š” ์• ๋…ธํ…Œ์ด์…˜์„ ํ™œ์šฉ์„ ์ง€ํ–ฅํ•œ๋‹ค.


1-2 Deserialization. JSON to ๊ฐ์ฒด

์ด์ œ ObjectMapper๋ฅผ ์ด์šฉํ•œ ์—ญ์ง๋ ฌํ™”์— ๋Œ€ํ•ด์„œ ์‚ดํŽด๋ณธ๋‹ค.

์—ญ์ง๋ ฌํ™”์—” readValue() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

@Test
void json_to_object() throws JsonProcessingException {
    // given
    ObjectMapper objectMapper = new ObjectMapper();

    String json = "{\"id\":\"123\",\"name\":\"binghe\",\"age\":28}";

    // when
    Member member = objectMapper.readValue(json, Member.class);

    // then
    assertThat(member.getId()).isEqualTo("123");
    assertThat(member.getName()).isEqualTo("binghe");
    assertThat(member.getAge()).isEqualTo(28);
}

readValue()์˜ ์ฒซ ๋ฒˆ์งธ ๋งค๊ฐœ๋ณ€์ˆ˜๋ก  JSON (๋ฌธ์ž์—ด, ๋˜๋Š” ์ŠคํŠธ๋ฆผ, ํŒŒ์ผ)์˜ ์†Œ์Šค๋ฅผ ๋„ฃ๊ณ , ๋‘ ๋ฒˆ์งธ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์—ญ์ง๋ ฌํ™”ํ•  ๊ฐ์ฒด์˜ ํด๋ž˜์Šค๋ฅผ ๋„ฃ์–ด์ฃผ๋ฉด ๋œ๋‹ค.


Jackson ObjectMapper๊ฐ€ JSON ํ•„๋“œ์™€ Java ํ•„๋“œ๋ฅผ ์ผ์น˜์‹œํ‚ค๋Š” ๋ฐฉ๋ฒ•

๋ฌธ์ž์—ด์ธ JSON๋ฅผ ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ (์—ญ์ง๋ ฌํ™”)ํ•˜๊ธฐ ์œ„ํ•ด์„  JSON ํ•„๋“œ์™€ POJO์˜ ํ•„๋“œ๋ฅผ ๋งคํ•‘์‹œ์ผœ์•ผํ•œ๋‹ค.

์ฆ‰, JSON๋‚ด nameํ•„๋“œ์™€ Member ๊ฐ์ฒด๋‚ด name ํ•„๋“œ๋ฅผ ๋งคํ•‘์‹œ์ผœ์•ผํ•œ๋‹ค.

Jackson์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ฐ์ฒด์˜ getter, setter ๋ฉ”์„œ๋“œ ์ด๋ฆ„์„ ํ†ตํ•ด JSON ํ•„๋“œ์™€ POJO ํ•„๋“œ๋ฅผ ๋งคํ•‘์‹œํ‚จ๋‹ค.

Jackson์€ getter ๋ฐ setter ๋ฉ”์„œ๋“œ ์ด๋ฆ„์˜ "get" ๋ฐ "set" ๋ถ€๋ถ„์„ ์ œ๊ฑฐํ•˜๊ณ  ๋‚˜๋จธ์ง€ ์ด๋ฆ„์˜ ์ฒซ ๋ฒˆ์งธ ๋ฌธ์ž๋ฅผ ์†Œ๋ฌธ์ž๋กœ ๋ณ€ํ™˜ํ•œ ์ด๋ฆ„๊ณผ JSON ํ•„๋“œ๋ฅผ ๋งคํ•‘์‹œ์ผœ ์—ญ์ง๋ ฌํ™”ํ•œ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, name์ด๋ผ๋Š” JSON ํ•„๋“œ๋Š” POJO๋‚ด getName() ํ˜น์€ setName()๋ฉ”์„œ๋“œ๋ฅผ ์ฐพ์•„ "get", "set" ๋ถ€๋ถ„์„ ์ œ๊ฑฐํ•˜๊ณ  Name์„ name์œผ๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ JSON ํ•„๋“œ์™€ ๋งคํ•‘์‹œํ‚จ๋‹ค.

๋งŒ์•ฝ ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ๋งคํ•‘์‹œํ‚ค๊ณ ์‹ถ๋‹ค๋ฉด, ์ปค์Šคํ…€ Deserializer๋ฅผ ๊ตฌํ˜„ํ•˜์—ฌ ObjectMapper์— ์ถ”๊ฐ€ํ•ด์ฃผ๋ฉด๋˜๋ฉฐ, ๋‹ค์–‘ํ•œ Jackson ์• ๋…ธํ…Œ์ด์…˜์„ ํ†ตํ•ด์„œ๋„ ์ปค์Šคํ…€ํ•  ์ˆ˜ ์žˆ๋‹ค.


JSON to ์ž๋ฐ” ๋ฐฐ์—ด

ObjectMapper๋Š” JSON ๋ฐฐ์—ด ๋ฌธ์ž์—ด์—์„œ ๊ฐ์ฒด ๋ฐฐ์—ด๋กœ ์—ญ์ง๋ ฌํ™”ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

๋‹ค์Œ์€ JSON ๋ฐฐ์—ด ๋ฌธ์ž์—ด์—์„œ ๊ฐ์ฒด ๋ฐฐ์—ด์„ ์ฝ๋Š” ์˜ˆ์‹œ๋‹ค.

@Test
void json_array_to_objects() throws JsonProcessingException {
    // given
    ObjectMapper objectMapper = new ObjectMapper();

    String json = "[{\"id\":\"123\",\"name\":\"binghe\",\"age\":28},{\"id\":\"456\",\"name\":\"binghe2\",\"age\":29}]";

    // when
    Member[] members = objectMapper.readValue(json, Member[].class);

    // then
    assertThat(members.length).isEqualTo(2);
    assertThat(members[0].getId()).isEqualTo("123");
    assertThat(members[0].getName()).isEqualTo("binghe");
    assertThat(members[0].getAge()).isEqualTo(28);
    assertThat(members[1].getId()).isEqualTo("456");
    assertThat(members[1].getName()).isEqualTo("binghe2");
    assertThat(members[1].getAge()).isEqualTo(29);
}

JSON to ๋ฆฌ์ŠคํŠธ

๋ฐฐ์—ด๊ณผ ๋™์ผํ•˜๊ฒŒ ๋ฆฌ์ŠคํŠธํƒ€์ž…๋„ ์—ญ์ง๋ ฌํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค.

@Test
void json_list_to_objects() throws JsonProcessingException {
    // given
    ObjectMapper objectMapper = new ObjectMapper();

    String json = "[{\"id\":\"123\",\"name\":\"binghe\",\"age\":28},{\"id\":\"456\",\"name\":\"binghe2\",\"age\":29}]";

    // when
    List<Member> members = objectMapper.readValue(json, new TypeReference<List<Member>>() {});

    // then
    assertThat(members.size()).isEqualTo(2);
    assertThat(members.get(0).getId()).isEqualTo("123");
    assertThat(members.get(0).getName()).isEqualTo("binghe");
    assertThat(members.get(0).getAge()).isEqualTo(28);
    assertThat(members.get(1).getId()).isEqualTo("456");
    assertThat(members.get(1).getName()).isEqualTo("binghe2");
    assertThat(members.get(1).getAge()).isEqualTo(29);
}

TypeRefenrece ์‚ฌ์šฉ ์ด์œ 

์œ„ ์˜ˆ์‹œ์—์„œ ์ค‘์š”ํ•œ ์ ์€ readValue()์˜ ๋‘ ๋ฒˆ์งธ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ TypeReference๋ฅผ ๋„˜๊ฒจ์ค€๋‹ค๋Š” ์ ์ด๋‹ค.

์ด๋•Œ TypeReference๋ฅผ ์‚ฌ์šฉํ•˜์ง€์•Š๊ณ  List<Member>.class๋ฅผ ๋„˜๊ฒจ์ฃผ๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

์œ„์™€ ๊ฐ™์€ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ์ด์œ ๋ฅผ ์ดํ•ดํ•˜๊ธฐ์œ„ํ•ด์„  ์ž๋ฐ”์˜ ์ œ๋„ค๋ฆญ์„ ๋จผ์ € ์ดํ•ดํ•ด์•ผํ•œ๋‹ค.

์ž๋ฐ”๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์ œ๋„ค๋ฆญ์œผ๋กœ ๋„˜๊ฒจ์ง„ ๊ฐ์ฒด ํƒ€์ž…์€ ๋Ÿฐํƒ€์ž„์—” ์‚ฌ๋ผ์ง„๋‹ค. ๊ทธ๋Ÿฌ๋ฏ€๋กœ List.class ํ˜น์€ List<Member>.class๋ฅผ ๋„˜๊ธด๋‹ค๊ณ ํ•ด๋„ ์ž๋ฐ” ๋Ÿฐํƒ€์ž„์—” List.class๋กœ ํƒ€์ž…์ด ์†Œ๋ฉธ๋œ๋‹ค.

๋ฌธ์ œ๋Š” Jackson์ด JSON์„ Member ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•˜๊ณ ์žํ•  ๋•Œ, ์–ด๋–ค ๊ฐ์ฒด ํƒ€์ž…์œผ๋กœ ๋ณ€ํ™˜ํ•ด์•ผํ•˜๋Š”์ง€ ๋ชจ๋ฅด๊ธฐ๋•Œ๋ฌธ์— Jackson์€ ๊ธฐ๋ณธ์ ์œผ๋กœ LinkedHashMap์œผ๋กœ ์—ญ์ง๋ ฌํ™”ํ•˜๊ณ  ์—ญ์ง๋ ฌํ™”๋œ ๊ฐ์ฒด์— ์•ก์„ธ์Šคํ•˜๋ ค๊ณ ํ•˜๋ฉด ClassCastException์ด ๋ฐœ์ƒํ•˜๊ฒŒ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

์ด๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋Ÿฐํƒ€์ž„์—๋„ ์ž๋ฐ” JVM์ด ์–ด๋–ค ์ž๋ฐ” ํƒ€์ž…์œผ๋กœ ๋ณ€ํ™˜ํ• ์ง€ ์•Œ ์ˆ˜ ์žˆ๋„๋ก ํƒ€์ž…์„ ์†Œ๋ฉธํ•˜์ง€ ์•Š๊ณ  ๋ณด์กดํ•ด์•ผํ•˜๋ฉฐ, TypeReference๊ฐ€ ๋ฐ”๋กœ ์ด๋Ÿฌํ•œ ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•ด์ค€๋‹ค.

์ฐธ๊ณ 


JSON to Map

ObjectMapper๋Š” JSON ๋ฌธ์ž์—ด์—์„œ ์ž๋ฐ” Map ํƒ€์ž…์œผ๋กœ๋„ ์—ญ์ง๋ ฌํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค.

Map์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ฒƒ์€ ์ •ํ™•ํ•œ JSON ๊ตฌ์กฐ๋ฅผ ๋ฏธ๋ฆฌ ๋ชจ๋ฅด๋Š” ๊ฒฝ์šฐ ์œ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. JSON์˜ ๊ฐ ํ•„๋“œ๋Š” ์ž๋ฐ” Map์˜ key, value ์Œ์œผ๋กœ ๋ณ€ํ™˜๋œ๋‹ค.

@Test
void json_to_map() throws JsonProcessingException {
    // given
    ObjectMapper objectMapper = new ObjectMapper();

    String json = "{\"id\":\"123\",\"name\":\"binghe\",\"age\":28}";

    // when
    Map<String, Object> jsonMap = objectMapper.readValue(json, new TypeReference<Map<String, Object>>(){});

    // then
    assertThat(jsonMap.get("id")).isEqualTo("123");
    assertThat(jsonMap.get("name")).isEqualTo("binghe");
    assertThat(jsonMap.get("age")).isEqualTo(28);
}

๋’ค์—์„œ ๋‹ค๋ฃฐ JsonNode์™€ ๋น„์Šทํ•œ ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•˜๋„๋ก ์ž๋ฐ” Map์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.


์•Œ ์ˆ˜ ์—†๋Š” JSON ํ•„๋“œ ๋ฌด์‹œ

JSON๋‚ด์—” ์กด์žฌํ•˜๋Š” ํ•„๋“œ๊ฐ€ ์ž๋ฐ” ๊ฐ์ฒด์•ˆ์—” ํ•ด๋‹น ํ•„๋“œ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ๊ฐ€์žˆ๋‹ค.

Jackson์€ ๋””ํดํŠธ๋กœ ์ด๋Ÿฐ๊ฒฝ์šฐ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š”๋ฐ, ์ž๋ฐ” ๊ฐ์ฒด๋ณด๋‹ค JSON์— ๋” ๋งŽ์€ ํ•„๋“œ๊ฐ€ ์กด์žฌํ•ด๋„ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋„๋ก ํ•˜๋ ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ์„ค์ •ํ•˜๋ฉด๋œ๋‹ค.

objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

Primitive ํƒ€์ž… null์ธ ๊ฒฝ์šฐ ์˜ˆ์™ธ ๋ฐœ์ƒ์‹œํ‚ค๋„๋ก ์„ค์ •

์ž๋ฐ” ๊ฐ์ฒด๋‚ด Primitive Type์œผ๋กœ ๋œ ์ƒํƒœ๊ฐ’์ด JSON๋‚ด ํ•„๋“œ๊ฐ€ null์ธ ๊ฒฝ์šฐ Jackson์€ Primitive Type์˜ ๋””ํดํŠธ๋กœ ๋ณ€ํ™˜ํ•œ๋‹ค.

๋งŒ์•ฝ JSON๋‚ด ํ•„๋“œ๊ฐ€ null์ธ ์ƒํƒœ๋ฅผ Primitive Type์œผ๋กœ ๋ณ€ํ™˜ํ•˜๊ณ ์žํ•  ๋•Œ ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๊ณ ์‹ถ์œผ๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ์„ค์ •ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

ObjectMapper objectMapper = new ObjectMapper();

objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, true);

JsonNode๋ฅผ ์ด์šฉํ•œ ์ง๋ ฌํ™”, ์—ญ์ง๋ ฌํ™”


Jackson ์ง๋ ฌํ™” ์—ญ์ง๋ ฌํ™” ๋™์ž‘ ๋ฐฉ์‹ - JsonParser, JsonGenerator

ObjectMapper ๊ฐ์ฒด๋‚ด ์„ค๋ช…์„ ๋ณด๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ๋ช…์‹œ๋˜์–ด์žˆ๋‹ค.

Mapper (and ObjectReaders, ObjectWriters it constructs) will use instances of JsonParser and JsonGenerator for implementing actual reading/writing of JSON.

์ฐธ๊ณ