1. 개요
이 빠른 사용방법(예제)에서는 Java Enum이 Jackson 2로 직렬화 및 역직렬화 되는 방식을 제어하는 방법을 배웁니다 .
잭슨 2로 할 수 있는 다른 멋진 일들을 좀 더 깊이 파고들고 배우 려면 기본 잭슨 예제 로 가십시오 .
2. 열거형 표현 제어
다음 Enum을 정의해 보겠습니다.
public enum Distance {
KILOMETER("km", 1000),
MILE("miles", 1609.34),
METER("meters", 1),
INCH("inches", 0.0254),
CENTIMETER("cm", 0.01),
MILLIMETER("mm", 0.001);
private String unit;
private final double meters;
private Distance(String unit, double meters) {
this.unit = unit;
this.meters = meters;
}
// standard getters and setters
}
3. 열거형을 JSON으로 직렬화
3.1. 기본 열거형 표현
기본적으로 Jackson은 Java Enum을 간단한 문자열로 나타냅니다. 예를 들어:
new ObjectMapper().writeValueAsString(Distance.MILE);
결과:
"MILE"
그러나 이 Enum을 JSON 객체로 마샬링할 때 다음과 같은 결과를 얻고 싶습니다.
{"unit":"miles","meters":1609.34}
3.2. 열거형을 JSON 객체로
Jackson 2.1.2부터 이러한 종류의 표현을 처리할 수 있는 구성 옵션이 있습니다. 이것은 클래스 수준에서 @JsonFormat 어노테이션을 통해 수행할 수 있습니다.
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum Distance { ... }
이것은 Distance 에 대해 이 열거형 을 직렬화할 때 원하는 결과로 이어집니다 . 마일:
{"unit":"miles","meters":1609.34}
3.3. 열거형 및 @JsonValue
열거형에 대한 마샬링 출력을 제어하는 또 다른 간단한 방법은 getter에서 @JsonValue 어노테이션을 사용하는 것입니다.
public enum Distance {
...
@JsonValue
public String getMeters() {
return meters;
}
}
여기서 표현하는 것은 getMeters() 가 이 열거형의 실제 표현이라는 것입니다. 따라서 직렬화 결과는 다음과 같습니다.
1609.34
3.4. Enum용 사용자 지정 직렬 변환기
2.1.2 이전 버전의 Jackson을 사용하거나 열거형에 대해 더 많은 사용자 지정이 필요한 경우 사용자 지정 Jackson 직렬 변환기를 사용할 수 있습니다. 먼저 다음과 같이 정의해야 합니다.
public class DistanceSerializer extends StdSerializer {
public DistanceSerializer() {
super(Distance.class);
}
public DistanceSerializer(Class t) {
super(t);
}
public void serialize(
Distance distance, JsonGenerator generator, SerializerProvider provider)
throws IOException, JsonProcessingException {
generator.writeStartObject();
generator.writeFieldName("name");
generator.writeString(distance.name());
generator.writeFieldName("unit");
generator.writeString(distance.getUnit());
generator.writeFieldName("meters");
generator.writeNumber(distance.getMeters());
generator.writeEndObject();
}
}
그런 다음 직렬화할 클래스에 직렬화기를 적용할 수 있습니다.
@JsonSerialize(using = DistanceSerializer.class)
public enum TypeEnum { ... }
그 결과:
{"name":"MILE","unit":"miles","meters":1609.34}
4. JSON을 열거형으로 역직렬화
먼저 Distance 멤버 가 있는 City 클래스를 정의해 보겠습니다 .
public class City {
private Distance distance;
...
}
그런 다음 JSON 문자열을 Enum으로 역직렬화하는 다양한 방법에 대해 논의합니다.
4.1. 기본 동작
기본적으로 Jackson은 Enum 이름을 사용하여 JSON에서 역직렬화 합니다.
예를 들어 JSON을 역직렬화합니다.
{"distance":"KILOMETER"}
Distance.KILOMETER 개체 로 :
City city = new ObjectMapper().readValue(json, City.class);
assertEquals(Distance.KILOMETER, city.getDistance());
Jackson이 Enum 이름으로 JSON에서 대소문자를 구분하지 않고 역직렬화 하도록 하려면 ACCEPT_CASE_INSENSITIVE_ENUMS 기능 을 활성화하도록 ObjectMapper 를 사용자 지정 해야 합니다 .
다른 JSON이 있다고 가정해 보겠습니다.
{"distance":"KiLoMeTeR"}
이제 대소문자를 구분하지 않는 역직렬화를 수행해 보겠습니다.
ObjectMapper objectMapper = JsonMapper.builder()
.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS)
.build();
City city = objectMapper.readValue(json, City.class);
assertEquals(Distance.KILOMETER, city.getDistance());
위의 테스트에서 알 수 있듯이 JsonMapper 빌더 를 사용하여 ACCEPT_CASE_INSENSITIVE_ENUMS 기능을 활성화합니다.
4.2. @JsonValue 사용
Enum 을 직렬화 하기 위해 @JsonValue 를 사용하는 방법을 배웠습니다 . 역직렬화에도 동일한 어노테이션을 사용할 수 있습니다. 이것은 Enum 값이 상수이기 때문에 가능합니다.
먼저 getter 메서드 중 하나인 getMeters() 와 함께 @JsonValue 를 사용합니다 .
public enum Distance {
...
@JsonValue
public double getMeters() {
return meters;
}
}
getMeters() 메서드 의 반환 값은 Enum 개체를 나타냅니다. 따라서 샘플 JSON을 역직렬화할 때:
{"distance":"0.0254"}
Jackson은 getMeters() 반환 값이 0.0254인 Enum 객체를 찾습니다. 이 경우 객체는 거리입니다. 인치:
assertEquals(Distance.INCH, city.getDistance());
4.3. @JsonProperty 사용
@JsonProperty 어노테이션은 열거형 인스턴스에 사용됩니다.
public enum Distance {
@JsonProperty("distance-in-km")
KILOMETER("km", 1000),
@JsonProperty("distance-in-miles")
MILE("miles", 1609.34);
...
}
이 어노테이션을 사용하여 우리는 단순히 @JsonProperty 값 을 이 값으로 어노테이션이 달린 객체 에 매핑하도록 Jackson에 지시합니다 .
위 선언의 결과로 예제 JSON 문자열은 다음과 같습니다.
{"distance": "distance-in-km"}
Distance.KILOMETER 개체 에 매핑됩니다 .
assertEquals(Distance.KILOMETER, city.getDistance());
4.4. @JsonCreator 사용
Jackson은 @JsonCreator 로 어노테이션이 달린 메서드를 호출 하여 둘러싸는 클래스의 인스턴스를 가져옵니다.
JSON 표현을 고려하십시오.
{
"distance": {
"unit":"miles",
"meters":1609.34
}
}
그런 다음 @JsonCreator 어노테이션 을 사용하여 forValues() 팩토리 메서드를 정의합니다.
public enum Distance {
@JsonCreator
public static Distance forValues(@JsonProperty("unit") String unit,
@JsonProperty("meters") double meters) {
for (Distance distance : Distance.values()) {
if (
distance.unit.equals(unit) && Double.compare(distance.meters, meters) == 0) {
return distance;
}
}
return null;
}
...
}
@JsonProperty 어노테이션을 사용하여 JSON 필드를 메서드 인수와 바인딩하는 것에 유의하십시오 .
그런 다음 JSON 샘플을 역직렬화하면 결과가 표시됩니다.
assertEquals(Distance.MILE, city.getDistance());
4.5. 사용자 지정 디시리얼라이저 사용
설명된 기술을 사용할 수 없는 경우 사용자 지정 디시리얼라이저를 사용할 수 있습니다. 예를 들어 Enum 소스 코드에 액세스할 수 없거나 지금까지 다룬 어노테이션 중 하나 이상을 지원하지 않는 이전 Jackson 버전을 사용하고 있을 수 있습니다 .
사용자 지정 역직렬화 기사 에 따르면 이전 섹션에서 제공한 JSON을 역직렬화하기 위해 역직렬화 클래스를 만드는 것으로 시작합니다.
public class CustomEnumDeserializer extends StdDeserializer<Distance> {
@Override
public Distance deserialize(JsonParser jsonParser, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
JsonNode node = jsonParser.getCodec().readTree(jsonParser);
String unit = node.get("unit").asText();
double meters = node.get("meters").asDouble();
for (Distance distance : Distance.values()) {
if (distance.getUnit().equals(unit) && Double.compare(
distance.getMeters(), meters) == 0) {
return distance;
}
}
return null;
}
}
그런 다음 Enum에서 @JsonDeserialize 어노테이션을 사용하여 사용자 지정 deserializer를 지정합니다.
@JsonDeserialize(using = CustomEnumDeserializer.class)
public enum Distance {
...
}
결과는 다음과 같습니다.
assertEquals(Distance.MILE, city.getDistance());
5. 결론
이 기사에서는 Java Enums의 직렬화 및 역직렬화 프로세스와 형식을 더 잘 제어하는 방법을 설명했습니다 .
이러한 모든 예제와 코드 스니펫의 구현은 GitHub 에서 찾을 수 있습니다 .