- JSON 컨텐츠와 Java 객체를 매핑하기 위한 Jackson 라이브러리의 클래스
- 주의 할 점은 클래스 내부에서 많은 초기화가 일어나기 때문에 가능하다면 bean으로 등록하거나 static으로 사용하는게 성능상 유리
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class Member {
private String name;
private int age;
private String userId;
private String userPassword;
}
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.fasterxml.jackson.databind.ObjectMapper;
@Configuration
public class AppConfig {
@Bean
public ObjectMapper objectMapper() {
return new ObjectMapper();
}
}
import java.util.Map;
import org.springframework.stereotype.Controller;
import lombok.RequiredArgsConstructor;
import com.fasterxml.jackson.databind.ObjectMapper;
@Controller
@RequiredArgsConstructor
public class JoinController {
private final ObjectMapper objectMapper;
@PostMappping("/join")
public String join(@RequestParam String param) {
objectMapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
Member member = objectMapper.readValue(param, Member.class);
}
}
import org.springframework.stereotype.Controller;
import lombok.RequiredArgsConstructor;
import com.fasterxml.jackson.databind.ObjectMapper;
@Controller
@RequiredArgsConstructor
public class JoinController {
private static final ObjectMapper objectMapper = new ObjectMapper()
.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
@PostMappping("/join")
public String join(@RequestParam String param) {
objectMapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
Member member = objectMapper.readValue(param, Member.class);
}
}
객체를 JSON형태로 변경할 경우에는 writeValueAsString(객체) 형태로 사용
설명에 앞서 직렬화(serialize)라는 용어를 알 필요가 있습니다. 사전적인 의미로는 다음과 같습니다.
- 직렬화(serialize) : 메모리를 디스크에 저장하거나 네트워크 통신에 사용하기 위한 형태로 변환
- 역직렬화(deserialize) : 디스크에 저장한 데이터를 읽거나, 네트워크 통신으로 받은 데이터를 메모리에 쓸 수 있도록 변환
해당 형태는 JSON, Byte, XML 등의 다양하게 변환이 됩니다. 하지만 SpringFramework에서는 주로 JSON 형태의 통신을 일컫기 때문에 해당 개념으로 보시면 좋을 것 같습니다.
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class Member {
private String name;
private int age;
private String userId;
private String userPassword;
public String getBirthDay(int age) {
int currentYear = LocalDate.now().getYear();
LocalDate today = LocalDate.now();
return String.valueOf(currentYear - age);
}
}
해당 함수의 결과값이 JSON으로 파싱될 수 있다는 점을 항상 유의하여 get 으로 시작하는 메서드명 사용을 지양 습관도 좋은 방법이 될 수 있을것 같습니다.
import org.springframework.stereotype.Controller;
import lombok.RequiredArgsConstructor;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JsonConverter {
// bean 호출 혹은 static으로 선언
private static final ObjectMapper objectMapper = new ObjectMapper()
.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
public static Member fromJson(String json) throws JsonProcessingException {
return objectMapper.readValue(json, Member.class);
}
public static String toJson(Object object) throws JsonProcessingException {
return objectMapper.writeValueAsString(object);
}
}
- ObjectMapper를 통한 역할을 어노테이션을 통한 JSON 컨텐츠와 Java 객체를 매핑
클래스 단위 작동 방식으로 매핑하려는 JSON의 키값이 일정할 경우 사용
필드 단위 작동 방식으로 매핑하려는 JSON의 키값이 일정할 경우 사용
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public class Member {
private String name;
private int age;
private String userId;
private String userPassword;
}
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonProperty;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class Member {
private String name;
private int age;
@JsonProperty("user_id")
private String userId;
@JsonProperty("user_password")
private String userPassword;
}
- ObjectMapper는 로직상의 개별 커스텀이 필요하거나 예외 처리를 직접 커스텀 하는 경우 등 세밀한 조정이 필요한 경우
- 어노테이션 해당 객체가 통신 결과값을 주고 받는 것에만 사용되거나 키값 형태의 통일성이 높은 경우