일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- MySQL
- 정보처리기사실기 기출문제
- Java
- 정보처리기사 실기 기출문제
- 공부
- minikube
- Linux
- 오블완
- PETERICA
- kotlin
- Elasticsearch
- 정보처리기사 실기
- 코틀린 코루틴의 정석
- 티스토리챌린지
- 기록으로 실력을 쌓자
- kotlin coroutine
- APM
- Spring
- AWS EKS
- Kubernetes
- CKA 기출문제
- CloudWatch
- kotlin spring
- CKA
- Pinpoint
- aws
- kotlin querydsl
- IntelliJ
- AI
- mysql 튜닝
- Today
- Total
피터의 개발이야기
[Spring] Jackson Annotations 본문
json관련하여 jackson 라이브러리를 사용하고 있다.
jackson에서 재공하는 유용한 어노테이션을 정리한다.
Read+ Write Annotations
@JsonIgnore
public class TestIgnore {
@JsonIgnore
public long testId = 0;
public String name = null;
}
위 코드에서 testId는 JSON에서 읽거나 기록되지 않는다.
@JsonIgnoreProperties
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@JsonIgnoreProperties({"firstName", "lastName"})
public class PersonIgnoreProperties {
public long personId = 0;
public String firstName = null;
public String lastName = null;
}
@JsonIgnore과 마찬가지로 해당 필드리스트에 대해서 일거나 기록하지 않는다.
@JsonIgnoreType
import com.fasterxml.jackson.annotation.JsonIgnoreType;
public class PersonIgnoreType {
@JsonIgnoreType
public static class Address {
public String streetName = null;
public String houseNumber = null;
public String zipCode = null;
public String city = null;
public String country = null;
}
public long personId = 0;
public String name = null;
public Address address = null;
}
위의 예에서는 모든 Address인스턴스가 무시됩니다.
@JsonAutoDetect
import com.fasterxml.jackson.annotation.JsonAutoDetect;
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY )
public class PersonAutoDetect {
private long personId = 123;
public String name = null;
}
JsonAutoDetect.Visibility 클래스에는 접근제한 레벨 상수가 정의 되어 있다.
- ANY
- DEFAULT
- NON_PRIVATE
- NONE
- PROTECTED_AND_PRIVATE
- PUBLIC_ONLY
Read Annotations
@JsonSetter
{
"id" : 1234,
"name" : "John"
}
받고자 하는 JSON의 형태는 "id"이지만 Person에서는 "personId"에 맵핑할 수 있다.
public class Person {
private long personId = 0;
private String name = null;
public long getPersonId() {
return this.personId;
}
@JsonSetter("id")
public void setPersonId(long personId) {
this.personId = personId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@JsonAnySetter
받고자 하는 JSON의 형태에서 유동적인 형태로 데이터를 받고 싶을 때 사용한다.
JSON의 키, 밸류가 Map형태로 담아진다.
public class Bag {
private Map<String, Object> properties = new HashMap<>();
@JsonAnySetter
public void set(String fieldName, Object value){
this.properties.put(fieldName, value);
}
public Object get(String fieldName){
return this.properties.get(fieldName);
}
}
@JsonCreator
받아야 하는 JSON은 다음과 같다.
{
"id":1,
"theName":"My bean"
}
하지만 현재 사용하는 Entity와 매칭이 되지 않을 때에
아래의 방법은 유용하다.
public class BeanWithCreator {
public int id;
public String name;
@JsonCreator
public BeanWithCreator(
@JsonProperty("id") int id,
@JsonProperty("theName") String name) {
this.id = id;
this.name = name;
}
}
아래는 적용예제이다.
@Test
public void whenDeserializingUsingJsonCreator_thenCorrect()
throws IOException {
String json = "{\"id\":1,\"theName\":\"My bean\"}";
BeanWithCreator bean = new ObjectMapper()
.readerFor(BeanWithCreator.class)
.readValue(json);
assertEquals("My bean", bean.name);
}
@JacksonInject
어떤 데이터는 JSON을 통해 받지 않고 별도로 주입해야 하는 경우가 있다.
public class BeanWithInject {
@JacksonInject
public int id;
public String name;
}
테스트 코드 :
@Test
public void whenDeserializingUsingJsonInject_thenCorrect()
throws IOException {
String json = "{\"name\":\"My bean\"}";
InjectableValues inject = new InjectableValues.Std()
.addValue(int.class, 1);
BeanWithInject bean = new ObjectMapper().reader(inject)
.forType(BeanWithInject.class)
.readValue(json);
assertEquals("My bean", bean.name);
assertEquals(1, bean.id);
}
@JsonDeserialize
먼저 @JsonDeserialize를 사용하여 CustomDateDeserializer로 eventDate 속성을 역직렬화한다.
다시말해, 날짜 String의 형태로 직렬화된 상태에서
날짜 내부에서 쓸 수 있는 날짜 데이터로 변환되도록 역직렬화 작업을 수행한다.
public class EventWithSerializer {
public String name;
@JsonDeserialize(using = CustomDateDeserializer.class)
public Date eventDate;
}
사용자 지정 deserializer는 다음과 같다.
public class CustomDateDeserializer
extends StdDeserializer<Date> {
private static SimpleDateFormat formatter
= new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
public CustomDateDeserializer() {
this(null);
}
public CustomDateDeserializer(Class<?> vc) {
super(vc);
}
@Override
public Date deserialize(
JsonParser jsonparser,
DeserializationContext context) throws IOException {
String date = jsonparser.getText();
try {
return formatter.parse(date);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
}
테스트 코드
@Test
public void whenDeserializingUsingJsonDeserialize_thenCorrect()
throws IOException {
String json
= "{"name":"party","eventDate":"20-12-2014 02:30:00"}";
SimpleDateFormat df
= new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
EventWithSerializer event = new ObjectMapper()
.readerFor(EventWithSerializer.class)
.readValue(json);
assertEquals(
"20-12-2014 02:30:00", df.format(event.eventDate));
}
참고로, 직렬화방법에는 여러 Format이 존재한다.
- 표형태의 다량의 데이터를 직렬화할 때는 CSV형태
- 구조적인 데이터는 XML이나 JSON형태
Write Annotations
@JsonInclude
@JsonInclude 를 사용 하여 empty / null / 기본값이 있는 속성을 제외 할 수 있다.
아래는 null 대한 예제로 null은 제외한다.
@JsonInclude(Include.NON_NULL)
public class MyBean {
public int id;
public String name;
}
테스트 코드
public void whenSerializingUsingJsonInclude_thenCorrect()
throws JsonProcessingException {
MyBean bean = new MyBean(1, null);
String result = new ObjectMapper()
.writeValueAsString(bean);
assertThat(result, containsString("1"));
assertThat(result, not(containsString("name")));
}
@JsonInclude(JsonInclude.Include.ALWAYS) : 모든 값을 출력한다.
@JsonInclude(JsonInclude.Include.NON_EMPTY) :
- Collection, Map의 isEmpty()가 true 이면 제외한다.
- Array의 length가 0이면 제외한다.
- String의 length()가 0이면 제외한다.
@JsonInclude(JsonInclude.Include.NON_DEFAULT) :
- empty는 제외된다.
- primitive 타입이 디폴트 값이면 제외한다. (int / Integer : 0 , boolean / Boolean : false 등)
- Date의 timestamp가 0L이면 제외한다.
@JsonGetter
JSON의 키 값이 "theName"에서 "name"으로 지정해 준다.
getter 메서드명으로 키값을 정하지 않고 지정할 수 있다.
@Builder
public static class MyBean {
public int id;
private String name;
@JsonGetter("name")
public String getTheName() {
return name;
}
}
@JsonValue
getName 에 @JsonValue 해당 멤버필드가 이름을 통해 직렬화 시킴
public class PersonValue {
public long personId = 0;
public String name = null;
@JsonValue
public String toJson(){
return this.personId + "," + this.name;
}
}
직렬화 화면 이렇게 표출된다.
"0,null"
@JsonRawValue
@JsonRawValue 는 Jackson이 속성을 그대로 직렬화하여 JSON으로 변경
@Builder
public static class RawBean {
public String name;
@JsonRawValue
public String json;
}
//JSON
{
"name": "등록",
"json": "{\nstat\"\":false\n}"
}
//CONVERT
{
"name": "등록",
"json": {
"stat": false
}
}
참고
'Programming > Spring' 카테고리의 다른 글
[Spring] War 배포와 Jar 배포 시 resource 참조 문제 (0) | 2020.12.14 |
---|---|
Spring Profiles (0) | 2020.12.12 |
[SPRING BOOT] Retrofit vs Feign for Server Side (0) | 2020.12.08 |
[Spring] Spring schedule을 조건부로 활성화 하기 (0) | 2020.12.02 |
[Spring] @Transient (0) | 2020.12.02 |