구성된 Jackson ObjectMapper에서 예기치 않은 직렬화 동작
Jackson 2.10.5를 사용하여 동일한 java.util.Date
객체를 세 번 직렬화하고 있습니다.
- 처음으로 기본 Jackson
ObjectMapper
. 타임 스탬프가 보입니다. - 그런 다음 동일한을 구성
ObjectMapper
하고 다시 작성합니다. 나는 같은 결과를 얻습니다. - 그런 다음 새
ObjectMapper
를 구성하고 동일한 방식으로 구성합니다. JSON 목록에 다른 결과, 클래스 이름 및 타임 스탬프가 표시됩니다.
구성은 JSON 속성을 제외한ObjectMapper
모든 개체의 클래스 이름을 포함 하도록에 지시하기위한 것 입니다.java.util.Date
그래서 두 가지 질문이 있습니다. 첫 번째는 세 번째 경우에서 날짜 객체가 다르게 직렬화되는 이유입니다. PolymorphicTypeMapper
다르게 사용하는 것에 대한 조언을 주시면 감사하겠습니다.
두 번째는 첫 번째와 두 번째가 동일한 이유입니다 (Object 매퍼에 캐시 (아야!)가 있기 때문입니까?).
[편집 :이 사용 사례가 Jersey의 JSON 공급자라고 언급 했어야합니다. ObjectMapper
시작할 때 를 생성하고 구성하는 방법이 있지만 쓰기 단위로 구성 할 수있는 능력은 위의 테스트 코드에만 해당됩니다.]
private PolymorphicTypeValidator getPTV() {
return BasicPolymorphicTypeValidator.builder()
.denyForExactBaseType(Date.class)
.build();
}
@Test
public void serializationTest() {
try {
Date now = new Date();
// Create an object mapper and serialize the date
ObjectMapper om = new ObjectMapper();
String serialized1 = om.writeValueAsString(now); // result: 1605744866827
om.activateDefaultTypingAsProperty(getPTV(), ObjectMapper.DefaultTyping.EVERYTHING, "@class");
String serialized2 = om.writeValueAsString(now); // result: 1605744866827
ObjectMapper om2 = new ObjectMapper();
om2.activateDefaultTypingAsProperty(getPTV(), ObjectMapper.DefaultTyping.EVERYTHING, "@class");
String serialized3 = om2.writeValueAsString(now); // result: ["java.util.Date",1605744866827]
Logger.getLogger(SerializationTest.class).info(serialized1);
Logger.getLogger(SerializationTest.class).info(serialized2);
Logger.getLogger(SerializationTest.class).info(serialized3);
Assert.assertEquals("Unexpected change in serialization 1-2", serialized1, serialized2);
Assert.assertEquals("Unexpected change in serialization 1-3", serialized1, serialized3);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
출력은 다음과 같습니다.
INFO 2020-11-18 16:14:27,065 [main] <> test.SerializationTest : 1605744866827
INFO 2020-11-18 16:14:27,066 [main] <> test.SerializationTest : 1605744866827
INFO 2020-11-18 16:14:27,066 [main] <> test.SerializationTest : ["java.util.Date",1605744866827]
org.junit.ComparisonFailure: Unexpected change in serialization 1-3
Expected :1605744866827
Actual :["java.util.Date",1605744866827]
답변
읽기 문서 ,의 javadoc는 즉 ObjectMapper말한다 ( 굵은 내게로 하이라이트) :
매퍼 인스턴스는 인스턴스의 모든 구성 이 읽기 또는 쓰기 호출 전에 발생 하는 경우 완전히 스레드로부터 안전 합니다 . 매퍼 구성이 처음 사용 된 후 수정되면 변경 사항이 적용되거나 적용되지 않을 수 있으며 구성 호출 자체 가 실패 할 수 있습니다. 다른 구성을 사용해야하는 경우 두 가지 주요 가능성이 있습니다.
ObjectReader
읽기,ObjectWriter
쓰기를 위해 구성하고 사용 합니다 . 두 유형 모두 완전히 변경할 수 없으며의 팩토리 메서드ObjectMapper
또는 리더 / 라이터 자체를 사용하여 다른 구성으로 새 인스턴스를 자유롭게 만들 수 있습니다 . newObjectReader
s 및ObjectWriter
s의 구성은 매우 가벼운 작업이므로 필요에 따라 JSON의 선택적 들여 쓰기와 같은 구성을 위해 호출별로 생성하는 것이 적절합니다.구성 가능성의 특정의 종류를 통해 사용할 수없는 경우
ObjectReader
와ObjectWriter
, 당신은 사용해야 할 수도 있습니다 여러ObjectMapper
(:;, 사용자 정의 (비) 직렬 세트를 또는 혼합 된 온 - 더 - 플라이 주석 변경할 수 없습니다 예를 들어) 대신. 이 사용을 돕기 위해copy()
특정 구성으로 매퍼의 복제본을 만들고 사용하기 전에 복사 된 인스턴스의 구성을 허용 하는 방법을 사용할 수 있습니다. 참고copy()
작업이 새로운 건설로 비싼ObjectMapper
여러 작업을 사용하려는 경우, 당신은 여전히 풀과 재사용 매퍼해야 가능한 경우 : 인스턴스를.