[ Springboot ] Jackson 라이브러리와 POJO, JSON 변환
Springboot에서 컨트롤러를 개발하면, JSON으로 값을 받아 Java Object에 값을 저장하고,
반대로 Java Object 값을 JSON 으로 변환해서 응답으로 주는 경우가 많다.( 또는 XML )
직접 String 으로 JSON 을 만들거나, JSON 값을 Java Object에 일일히 값을 설정해줘도 되지만
Spring과 Jackson 라이브러리를 함께 사용하면, JSON <-> POJO 간 변환을 알아서 해준다.
POJO : Plain Old Java Object의 약자로 특정 자바 모델이나 기능, 프레임워크를 따르지 않는 순수? 자바 오브젝트 이다.
Jackson : Java를 위한 고성능 JSON 라이브러리이다. Spring에서는 기본으로 탑재가 되어있다.
POJO
먼저, JSON 값을 저장할 그리고, JSON 값으로 변환할 POJO class를 하나 만들어 준다.
@Getter
@Setter
public class UserVO {
private String name;
private String id;
}
Jackson은 Property 값을 기준으로 변환을 해주고, Getter/Setter의 이름을 프로퍼티로 사용을 한다.
( 클래스 멤버가 없어도 된다. 멤버 변수를 기준으로 property를 사용하기 위해서는 @JsonProperty를 사용하면 되는데 아래에서 추가로 설명을 한다. )
그래서 POJO <-> JSON 변환시에 JSON key값은 POJO의 property 값과 매치가 되어야 한다.
Controller - @RequestBody, @ResponseBody
이제, 컨트롤러에서 JSON을 입력 받고, 리턴해주는 부분을 작성해보자.
@PostMapping("/user")
@ResponseBody
public Object convertPOJOandJSON(@RequestBody UserVO userVO){
log.info("user id: " + userVO.getId() + ", user name:" + userVO.getName());
return userVO;
}
POST로 JSON을 받을 수 있도록 @PostMapping과 @RequestBody 를 선언한다.
POST로 JSON을 보내게 되면, UserVO객체에 JSON 값이 저장된다.
JSON 값을 리턴하도록 Object 리턴 타입과 @ResponseBody를 선언한다.
테스트
curl --location --request POST 'localhost:8080/user' \
--header 'Content-Type: application/json' \
--data-raw '{"name":"홍홍홍","id":"hong"}'
위와 같이 POST 요청을 보내면, UserVO 객체의 name과 id 변수에 값이 저장된다.
그리고, 이 객체를 리턴해 주면 아래와 같이
POJO의 property 명으로 Json의 key, POJO의 property 값으로 Json의 value가 만들어진다.
{"name":"홍홍홍","id":"hong"}
ResponseEntity
JSON 응답 시에, @ResponseBody 대신에 ResponseEntity 리턴 타입을 사용해도
body에 POJO가 들어가면 JSON 으로 변환이 되므로 용도에 맞게 골라서 사용을 하면 된다.
@PostMapping("/userEntity")
public ResponseEntity convertPOJOandHTTPJSON(@RequestBody UserVO userVO){
return ResponseEntity.ok().body(userVO);
}
Jackson Annotation
@JsonInclude
Json 에 property를 생략할지에 대한 조건을 줄 수 있는데, NON_EMPTY에 대해서만 간략하게 알아보자.
타입에 따라 생략 조건이 다른데 아래 표와 같다.
타입 | 생략 조건 |
String | length() 리턴 값이 0 |
Collection, Map | isEmpty() 리턴 값이 0 |
Others | null |
@Getter
@Setter
public class UserVO {
private String name;
private String id;
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private String mobileNum;
}
POST http://localhost:8080/user
Content-Type: application/json
{
"id": "xoxo",
"name": "홍홍"
}
# @JsonInclude(JsonInclude.Include.NON_EMPTY) 미사용시
{
"name": "홍홍",
"id": "xoxo",
"mobileNum": null
}
# @JsonInclude(JsonInclude.Include.NON_EMPTY) 사용시
{
"name": "홍홍",
"id": "xoxo"
}
@JsonProperty
Property 를 getter/setter의 이름을 가지고 사용하지만, 변수에 property이름을 지정해서 사용을 할 수도 있다.
mobileNum에 phone이라고 jsonproperty를 지정해주면, phone이라는 property 라는 이름을 사용하게 된다.
public class UserVO {
private String name;
private String id;
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@JsonProperty("phone")
private String mobileNum;
}
POST http://localhost:8080/user
Content-Type: application/json
{
"id": "xoxo",
"name": "홍홍",
"mobileNum": "a"
}
# 응답
{
"name": "홍홍",
"id": "xoxo"
}
POST http://localhost:8080/user
Content-Type: application/json
{
"id": "xoxo",
"name": "홍홍",
"phone": "a"
}
# 응답
{
"name": "홍홍",
"id": "xoxo",
"phone": "a"
}
@JsonUnwrapped
property 를 포함하지 않고, property 의 object만 포함을 해준다.( 배열에는 적용되지 않는다 )
public class UserVO {
private String name;
private String id;
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@JsonProperty("phone")
private String mobileNum;
@JsonUnwrapped
private AddressVO address;
}
# @JsonUnwrapped 미사용시,
# 요청
POST http://localhost:8080/user
Content-Type: application/json
{
"id": "xoxo",
"name": "홍홍",
"phone": "a",
"address": {"sido": "부산광역시","gungu": "해운대구"}
}
# 응답
{
"name": "홍홍",
"id": "xoxo",
"address": {
"sido": "부산광역시",
"gungu": "해운대구"
},
"phone": "a"
}
# @JsonUnwrapped 사용시,
# 요청
POST http://localhost:8080/user
Content-Type: application/json
{
"id": "xoxo",
"name": "홍홍",
"phone": "a",
"sido": "부산광역시","gungu": "해운대구"
}
# 응답
{
"name": "홍홍",
"id": "xoxo",
"sido": "부산광역시",
"gungu": "해운대구",
"phone": "a"
}
이 외에도, @JsonIgnore, @JsonIgnoreProperties, @JsonPropertyOrder 등의 annotation 이 있다.