기본 생성자, getter와 같은 부분을 생략하기 위해서 접근 제어자는 public으로 설정 했습니다.
@JsonAnyGetter
- Mappublic class Member {
public String name;
private Map<String, String> properties;
public Member(String name) {
this.name = name;
}
@JsonAnyGetter
public Map<String, String> getProperties() {
return properties;
}
public void add(String key, String val) {
this.properties.put(key, val);
}
}
Map 필드를 다루는데 유연성을 제공합니다.
@JsonGetter
- Getter 메서드 대체public class Member2 {
public int id;
private String name;
public Member2(int id, String name) {
this.id = id;
this.name = name;
}
@JsonGetter("name")
public String otherName() {
return name;
}
}
@JsonPropertyOrder
- 직렬화 순서@JsonPropertyOrder({ "name", "id" })
public class Member {
public int id;
public String name;
public Member(int id, String name) {
this.id = id;
this.name = name;
}
}
name, id 순서로 json데이터가 정렬됩니다.
@JsonValue
- 직렬화 대상 단일 필드, 단일 메서드public enum TypeEnumWithValue {
TYPE1(1, "one"), TYPE2(2, "two");
private Integer id;
private String name;
TypeEnumWithValue(Integer id, String name) {
this.id = id;
this.name = name;
}
@JsonValue
public String getName() {
return name;
}
}
@JsonValue는 전체 인스턴스를 직렬화 할 때 사용하는 단일 메서드입니다.
필드에도 적용이 가능합니다.
역직렬화에도 사용되면 converter
필요없는거 아닌가 라고 생각했는데 직렬화에만 사용됩니다.
@JsonRootName
- json root@JsonRootName(value = "member")
public class Member {
public int id;
public String name;
public Member(int id, String name) {
this.id = id;
this.name = name;
}
}
// @JsonRootName(value = "member") 적용 전후, root로 wrapping
{
"id": 1,
"name":"Kim"
}
{
"Member": {
"id": 1,
"name": "Lee"
}
}
해당 어노테이션이 적용되려면, ObejctMapper의 설정을 변경해야 합니다.
mapper.enable(SerializationFeature.WRAP_ROOT_VALUE);
@JsonSerialize
marshalling 과정에 custom serializer를 사용하도록 지정한다.
Jackson 라이브러리의 StdSerializer를 상속하여 custom serializer를 만들 수 있다.
marshalling과 serialization은 차이가 있다. serialization은 객체를 byte stream으로 변환하는 것 만을 의미한다. 이에 반해 marshalling은 객체를 저장이나 전송을 위해 적당한 자료 형태로 변형하는 것을 의미한다.
StdSerializer
or JsonSerializer
를 구현해서 사용
public class CustomSerializer extends JsonSerializer<LocalDate> {
private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
@Override
public void serialize(LocalDate value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeString(formatter.format(value));
}
}
// 특정 필드 적용
public class MyObject {
@JsonSerialize(using = CustomSerializer.class)
private LocalDate date;
// ...
}
// 공통 적용
@JsonComponent
public class CustomSerializer extends JsonSerializer<LocalDate> {**
bean으로 사용 가능하지만 @JsonComponent
로 등록하면 직렬화될 때, 자동으로 해당 포멧에 사용됩니다.
@JsonProperty
- 직렬화, 역직렬화에 해당 이름 사용@JsonProperty("MyNameIs")
private String name;
@JsonCreator
- 역직렬화 생성자 or 팩토리 지정json 데이터의 key값이 원하는 형태로 오지 않는 경우, 변경해서 역직렬화를 할 수 있다.
public class Member {
public int id;
public String name;
@JsonCreator
public Member(@JsonProperty("id") int id, @JsonProperty("otherName") String name) {
this.id = id;
this.name = name;
}
}
@JsonAnySetter
- map 객체에 역직렬화 활용
public class Member {
private String name;
private Map<String, String> properties = new HashMap<>();
@JsonAnySetter
public void add(String key, String value) {
properties.put(key, value);
}
public String getName() {
return name;
}
public Map<String, String> getProperties() {
return properties;
}
public static void main(String[] args) throws JsonProcessingException, ParseException {
String json = "{\"name\":\"Jay\",\"favorite\":\"chicken\",\"hobby\":\"tennis\"}";
Member member = new ObjectMapper().readerFor(Member.class).readValue(json);
System.out.println(member.getProperties());
}
}
@JsonDeserialize
- 역직렬화 형식 지정public class Event {
public String name;
@JsonDeserialize(using = CustomDateDeserializer.class)
public Date eventDate;
}
---------------------------------------------------------------
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 parser, DeserializationContext ctxt) throws IOException {
String date = parser.getText();
try {
return formatter.parse(date);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
}
@JsonAlias
- 역직렬화 대상 이름을 여러개 지정public class Member {
@JsonAlias({"name", "his_name", "her_name"})
public String name;
public String hobby;
}
@JsonIgnoreProperties
, @JsonIgnore
- 필드제외@JsonIgnoreProperties({"id"}) // 클래스 레벨
public class Member {
------------------------------------------------------------
@JsonIgnore // 필드 레벨
public int id;
@JsonInclude
- null 제외@JsonInclude(JsonInclude.Include.NON_NULL)
public class Member {
@JsonAutoDetect
- 직렬화 접근제어자로 대상 선정@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
// private 필드까지 직렬화 대상
// sonAutoDetect의 가시성 범위는 ANY, NON_PRIVATE, PROTECTED_AND_PUBLIC 등등
아래와 같은 옵션을 준 objectMapper를 사용하자.
public void disable_jackson_annotation() {
ObjectMapper mapper = new ObjectMapper();
mapper.disable(MapperFeature.USE_ANNOTATIONS);
...
}
특정 deserializer를 사용하는 DTO가 있는데, 해당 DTO로 특정 값을 hash하고 있는 상황에서,
해당 DTO로 데이터를 받으면서 hashing 하고, 다시 외부와 통신하고, 다시 데이터를 받을 때, 해당 DTO로 받을 때, 두 번 hasing되는 문제가 발생했다고 합니다.
따라서 해당 DTO를 다시 사용하려면 어노테이션을 비활성화한 objectMapper를 통해서 해결 할 수 있습니다.