Link
Today
Total
07-02 09:34
Archives
관리 메뉴

초보개발자 긍.응.성

Jackson Annotation 정리 (1) (Serialization Annotation) 본문

Spring/Jackson

Jackson Annotation 정리 (1) (Serialization Annotation)

긍.응.성 2020. 9. 10. 23:24
반응형

Jackson에서 사용하는 Annotation에 대해 정리한다. Baeldung (Jackson Annotation Example)에 정리된 글을 참고하였다.

1. Jackson Serialization Annotations

1.1 @JsonAnyGetter

Map 필드에 대해서 일반 properties로 처리한다

public class ExtendableBean {
	private String name;
	private Map<String, String> properties;

	@JsonAnyGetter
	public Map<String, String> getProperties() {
		return properties;
	}
}
/** @JsonAnyGetter 적용 전 */
{
  "name" : "My bean",
  "properties" : {
    "attr2" : "val2",
    "attr1" : "val1"
  }
}

/** @JsonAnyGetter 적용 후 */
{
  "name" : "My bean",
  "attr2" : "val2",
  "attr1" : "val1"
}

 

1.2 @JsonGetter

method에 대하여 value로 정한 필드의 getter로 지정한다. 아래의 예시는 getTheName() 메서드를 name 필드의 getter로 지정한 모습이다. 즉, serialization 과정에서 key=namevalue=getTheName()이다.

public class MyBean {
    public int id;
    private String name;
 
    @JsonGetter("name")
    public String getTheName() {
        return name;
    }
}

 

1.3 @JsonPropertyOrder

serialization 순서를 정의한다.

@JsonPropertyOrder({ "name", "id" })
public class MyBean {
    public int id;
    public String name;
}
/** @JsonPropertyOrder 적용 전 */
{
  "id" : 1,
  "name" : "My bean"
}

/** @JsonPropertyOrder 적용 후 */
{
  "name" : "My bean",
  "id" : 1
}

 

1.4 @JsonRawValue

메서드나 필드에 적용되며, 그 필드를 그대로 직렬화하여 JSON 값으로 여긴다.

public class RawBean {
    public String name;
 
    @JsonRawValue
    public String json;
}
@Test
public void testJsonRawValue() throws JsonProcessingException {
    RawBean rawBean = new RawBean("My bean", "{\"key\":\"value\",\"isTrue\":false}");

    System.out.println(new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(rawBean));
}

/** @JsonRawValue 적용 전 */
{
  "name" : "My bean",
  "json" : "{\"key\":\"value\",\"isTrue\":false}"
}

/** @JsonRawValue 적용 후 */
{
  "name" : "My bean",
  "json" : {"key":"value","isTrue":false}
}

 

1.5 @JsonValue

하나의 인스턴스를 직렬화하는것에 있어 하나의 메서드를 지정하도록 한다. 아래의 예시는 Enum타입 TypeEnumWithValue을 직렬화 시 value로 getName() 메서드를 사용하도록 지정한 것이다. 

public enum TypeEnumWithValue {
	TYPE1(1, "Type A"), TYPE2(2, "Type 2");

	private Integer id;
	private String name;

	TypeEnumWithValue(Integer id, String name) {
		this.id = id;
		this.name = name;
	}

	@JsonValue
	public String getName() {
		return name;
	}
}
@Test
public void testJsonValue() throws JsonProcessingException {
    System.out.println(new ObjectMapper().writeValueAsString(TypeEnumWithValue.TYPE1));
    System.out.println(new ObjectMapper().writeValueAsString(TypeEnumWithValue.TYPE2));
}

/** 적용 전 */
"TYPE1"
"TYPE2"

/** @JsonValue 적용 후*/
"Type A"
"Type 2"

 

1.6 @JsonRootName

Class, Enum, Interface위에 선언되어 해당 클래스가 wrapping 될 수 있다면, value가 root wrapper로 처리되도록 한다. 이 애노테이션은 ObjectMapper에서도 함께 enable.(SerializationFeature.WRAP_ROOT_VALUE)를 처리해주어야 동작한다. 주의할 점은 ObjectMapper에서만 처리하고 @JsonRootName 애노테이션을 붙여주지 않는다면 기본으로 root wrapper는 클래스의 이름으로 처리가 된다 (이러한 처리는 깔끔하지 못하다). 

@JsonRootName(value = "user")
public class UserWithRoot {
    public int id;
    public String name;
}
@Test
public void testJsonRootName() throws JsonProcessingException {
    UserWithRoot userWithRoot = new UserWithRoot(1, "changwoo.son");

    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.enable(SerializationFeature.WRAP_ROOT_VALUE); // enable wrapping
    System.out.println(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(userWithRoot));
}

/** @JsonRootName, SerializationFeature.WRAP_ROOT_VALUE 적용 전 */
{
  "id" : 1,
  "name" : "changwoo.son"
}

/** @JsonRootName 적용 전, SerializationFeature.WRAP_ROOT_VALUE 적용 후 */
{
  "UserWithRoot" : {
    "id" : 1,
    "name" : "changwoo.son"
  }
}

/** @JsonRootName, SerializationFeature.WRAP_ROOT_VALUE 적용 후 */
{
  "user" : {
    "id" : 1,
    "name" : "changwoo.son"
  }
}

 

1.7 @JsonSerialize

marshalling 과정에 custom serializer를 사용하도록 지정한다.

marshalling과 serialization은 차이가 있다. serialization은 객체를 byte stream으로 변환하는 것 만을 의미한다. 이에 반해 marshalling은 객체를 저장이나 전송을 위해 적당한 자료 형태로 변형하는 것을 의미한다.

Jackson 라이브러리의 StdSerializer를 상속하여 custom serializer를 만들 수 있다.

아래의 예시에선 Date 객체를 CustomDateSerializer를 이용하여 직렬화하도록 지정해주었다.  

public class EventWithSerializer {
    public String name;
 
    @JsonSerialize(using = CustomDateSerializer.class)
    public Date eventDate;
}
public class CustomDateSerializer extends StdSerializer<Date> {

	private static SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");

	public CustomDateSerializer() {
		this(null);
	}

	public CustomDateSerializer(Class<Date> t) {
		super(t);
	}

	@Override
	public void serialize(Date value, JsonGenerator gen, SerializerProvider provider) throws IOException {
		gen.writeString(formatter.format(value));
	}
}
@Test
public void testJsonSerialize() throws JsonProcessingException, ParseException {
	SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");

	String toParse = "2020-09-10 01:23:45";
	Date date = format.parse(toParse);
	EventWithSerializer event = new EventWithSerializer("party", date);

	System.out.println(new ObjectMapper().writeValueAsString(event));
}

/** @JsonSerialize 적용 전 */
{
  "name" : "party",
  "eventDate" : 1599668625000
}

/** @JsonSerialize 적용 후 */
{
  "name" : "party",
  "eventDate" : "2020-09-10 01:23:45"
}

 

반응형
Comments