Spring - HttpMessageConverter, ObjectMapper

Jackson 라이브러리의 ObjectMapper

Posted by Yan on November 15, 2023

ObjectMapper란?

  • JSON 컨텐츠를 Java 객체로 deserialization 하거나 Java 객체를 JSON으로 serialization 할 때 사용하는 Jackson 라이브러리의 클래스이다.
  • ObjectMapper는 생성 비용이 비싸기 때문에 bean/static으로 처리하는 것이 좋다.

Java 객체를 Json으로

1
2
3
4
5
6
7
8
9
10
11
public class Car {

    private String color;
    private String type;

    // standard getters setters
}

ObjectMapper objectMapper = new ObjectMapper();
Car car = new Car("yellow", "renault");
objectMapper.writeValue(new File("target/car.json"), car);

결과값

1
{"color":"yellow","type":"renault"}
writeValueAsString
  • 자바객체에서 string Json 반환
writeValueAsBytes
  • 자바객체에서 bytes Json 반환

Json을 자바 객체로

1
2
3
4
5
6
7
String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }";
Car car = objectMapper.readValue(json, Car.class);	

Car car = objectMapper.readValue(new File("src/test/resources/json_car.json"), Car.class);
// 또는 url사용

Car car = objectMapper.readValue(new URL("file:src/test/resources/json_car.json"), Car.class);

Jackson 라이브러리란?

Jackson은 JSON 데이터 구조를 처리해주는 라이브러리

작동 방식

  • Jackson은 JSON데이터를 출력하기 위한 MappingJacksonHttpMessageConverter를 제공한다.
  • 만약 스프링 MessageConverter를 위의 MappingJacksonHttpMessageConverter으로 등록한다면, 컨트롤러가 리턴하는 객체를 다시 뜯어(자바 리플렉션 사용), Jackson의 ObjectMapper API로 JSON 객체를 만들고 난 후, 출력하여 JSON데이터를 완성한다.
  • Spring 3.1 이후로 만약 클래스패스에 Jackson 라이브러리가 존재한다면, 자동적으로 MessageConverter가 등록된다.

기본 동작 원리

  • Jackson은 기본적으로 프로퍼티로 동작한다.
  • Java는 프로퍼티를 제공하는 문법이 없습니다. (멤버변수랑은 다름)
  • Java의 프로퍼티는 보통 Getter 와 Setter의 이름 명명 규칙으로 정해진다.
  • 프로퍼티는 Getter, Setter기준이므로 멤버변수 이름을 변경하더라도 상관 없다.
  • 많은 라이브러리가 해당 프로퍼티 개념으로 작동한다.
  • JSON데이터로 출력되기 위해서는 멤버변수의 유무가 아닌 프로퍼티 즉, Getter, Setter를 기준으로 작동한다.

HttpMessageConverter

@ResponseBody 사용 원리

  • HTTP Body에 문자 내용을 직접 반환
  • viewResolver 대신에 HttpMessageConverter가 동작함
  • 기본 문자처리 : StringHttpMessageConverter
  • 기본 객체처리 : MappingJackson2HttpMessageConverter
  • byte처리 등등 기타 여러 HttpMessageConverter가 기본으로 등록되어 있음

응답의 경우 클라이언트의 HTTP Accept 헤더와 서버의 컨트롤러 반환 타입 정보 등을 조합해서 HttpMessageConverter가 선택된다.

MessageConverter

  • HTTP 메세지 컨버터는 HTTP요청, HTTP응답(메세지 바디를 객체로 바꿔서 컨트롤러에 파라미터로 넘겨주는 일) 둘 다 사용한다.

  • read, write : 메세지 컨버터를 통해서 메세지를 읽고 쓰는 기능

  • 스프링 부트의 다양한 메세지 컨버터는, 대상 클래스의 타입과 미디어 타입 둘 다 체크해서 사용여부를 결정한다.

  1. ByteArrayHttpMessageConverter : byte[] 데이터를 처리
    • 클래스타입 : byte[]
    • 미디어타입 : */*
  2. StringHttpMessageConverter : String 문자로 데이터를 처리
    • 클래스타입 : String
    • 미디어타입 : */*
  3. MappingJackson2HttpMessageConverter : application/json처리
    • 클래스타입 : HashMap
    • 미디어타입 : application/json관련

스프링 MVC가 HTTP 메시지 컨버터를 적용하는 경우

  • HTTP 요청: @RequestBody, HttpEntity(RequestEntity)

  • HTTP 응답; @ResponseBody, HttpEntity(ResponseEntity)

👈 HTTP 요청 데이터 읽기 동작 원리

  1. HTTP 요청이 오고, 컨트롤러에서 @RequestBody, HttpEntity 파라미터를 사용한다.

  2. 메세지 컨버터가 메세지를 읽을 수 있는지 확인하기 위해 canRead()를 호출한다.
    • 대상 클래스 타입을 지원하는지 체크 (byte[], String 등)
    • HTTP 요청의 Content-Type 미디어 타입을 지원하는지 체크 (text/plain, application/json, */*)
  3. canRead()조건을 만족하면 read()를 호출해서 객체 생성하고, 반환한다.

👉 HTTP 응답 데이터 읽기 동작 원리

  1. 컨트롤러에서 @ResonseBody, HttpEntity 로 값이 반환된다.

  2. 메세지 컨버터가 메세지를 쓸 수 있는지 확인하기 위해 canWrite()를 호출한다.
    • 대상 클래스 타입을 지원하는지 체크 (byte[], String 등)
    • HTTP 요청의 Accept 미디어 타입을 지원하는지 체크 (text/plain, application/json, */*)
  3. canWrite()조건을 만족하면 write()를 호출해서 HTTP응답 메세지 바디에 데이터를 생성한다.
reference

Intro to the Jackson ObjectMapper [Java] ObjectMapper를 이용하여 JSON 파싱하기
[Spring] Jackson 라이브러리 이해하기.
스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 Spring MVC - Message Converter