Java 8 LocalDateTime에서 Jackson JSON 매퍼를 어떻게 사용합니까?
org.codehaus.jackson.map.JsonMappingException : JSON 문자열에서 [단순 유형, 클래스 java.time.LocalDateTime] 유형의 값을 인스턴스화 할 수 없습니다. 단일 문자열 생성자 / 공장 메소드 없음 (참조 체인을 통해 : MyDTO [ “field1”]-> SubDTO [ “date”])
답변
여기서는 사용자 정의 시리얼 라이저 / 디시리얼라이저를 사용할 필요가 없습니다. jackson-modules-java8의 datetime 모듈을 사용하십시오 .
Jackson이 Java 8 날짜 및 시간 API 데이터 유형 (JSR-310)을 인식하도록하는 데이터 유형 모듈.
- 지속
- 즉시
- LocalDateTime
- 현지 날짜
- 현지 시각
- 월 일
- 오프셋 날짜
- 오프셋 시간
- 기간
- 년
- YearMonth
- ZonedDateTime
- ZoneId
- ZoneOffset
답변
업데이트 : 역사적인 이유로이 답변을 남기지 만 권장하지 않습니다. 위의 허용 된 답변을 참조하십시오.
Jackson에게 사용자 정의 직렬화 클래스를 사용하여 맵핑하도록 지시하십시오.
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
private LocalDateTime ignoreUntil;
사용자 정의 클래스를 제공하십시오.
public class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
@Override
public void serialize(LocalDateTime arg0, JsonGenerator arg1, SerializerProvider arg2) throws IOException {
arg1.writeString(arg0.toString());
}
}
public class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
@Override
public LocalDateTime deserialize(JsonParser arg0, DeserializationContext arg1) throws IOException {
return LocalDateTime.parse(arg0.getText());
}
}
임의의 사실 : 클래스 위에 중첩하고 정적으로 만들지 않으면 오류 메시지가 이상합니다.
org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json;charset=UTF-8' not supported
답변
fasterxml의 ObjectMapper 클래스를 사용하는 경우 기본적으로 ObjectMapper는 LocalDateTime 클래스를 이해하지 못하므로 gradle / maven에 다른 종속성을 추가해야합니다.
compile 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.7.3'
이제이 라이브러리에서 제공하는 데이터 유형 지원을 objectmapper 객체에 등록해야합니다.이 작업은 다음과 같이 수행 할 수 있습니다.
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.findAndRegisterModules();
이제 jsonString에서 다음과 같이 java.LocalDateTime 필드를 쉽게 넣을 수 있습니다.
{
"user_id": 1,
"score": 9,
"date_time": "2016-05-28T17:39:44.937"
}
이 모든 작업을 수행하면 Json 파일에서 Java 객체로의 변환이 정상적으로 작동합니다. 다음과 같이 파일을 읽을 수 있습니다.
objectMapper.readValue(jsonString, new TypeReference<List<User>>() {
});
답변
이 maven 종속성은 문제를 해결합니다.
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.6.5</version>
</dependency>
내가 어려움을 겪은 한 가지는 직렬화 해제 중에 ZonedDateTime 시간대가 GMT로 변경된다는 것입니다. 기본적으로 jackson은이를 컨텍스트에서 하나로 대체합니다. 영역을 유지하려면이 ‘기능’을 비활성화해야합니다.
Jackson2ObjectMapperBuilder.json()
.featuresToDisable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE)
답변
스프링 부트 를 사용하는 동안 비슷한 문제가 발생했습니다 . Spring boot 1.5.1.RELEASE를 사용하면 종속성을 추가하기 만하면됩니다.
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
답변
Jersey를 사용하는 경우 다른 사람들이 제안한대로 Maven 종속성 (jackson-datatype-jsr310)을 추가하고 다음과 같이 객체 매퍼 인스턴스를 등록해야합니다.
@Provider
public class JacksonObjectMapper implements ContextResolver<ObjectMapper> {
final ObjectMapper defaultObjectMapper;
public JacksonObjectMapper() {
defaultObjectMapper = createDefaultMapper();
}
@Override
public ObjectMapper getContext(Class<?> type) {
return defaultObjectMapper;
}
private static ObjectMapper createDefaultMapper() {
final ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
return mapper;
}
}
리소스에 Jackson을 등록 할 때 다음과 같이이 매퍼를 추가해야합니다.
final ResourceConfig rc = new ResourceConfig().packages("<your package>");
rc
.register(JacksonObjectMapper.class)
.register(JacksonJaxbJsonProvider.class);
답변
jackson-modules-java8
어떤 이유로 든 사용할 수없는 경우 and & 를 long
사용하여 인스턴트 필드를 직렬화 해제 할 수 있습니다 .@JsonIgnore
@JsonGetter
@JsonSetter
public class MyBean {
private Instant time = Instant.now();
@JsonIgnore
public Instant getTime() {
return this.time;
}
public void setTime(Instant time) {
this.time = time;
}
@JsonGetter
private long getEpochTime() {
return this.time.toEpochMilli();
}
@JsonSetter
private void setEpochTime(long time) {
this.time = Instant.ofEpochMilli(time);
}
}
예:
@Test
public void testJsonTime() throws Exception {
String json = new ObjectMapper().writeValueAsString(new MyBean());
System.out.println(json);
MyBean myBean = new ObjectMapper().readValue(json, MyBean.class);
System.out.println(myBean.getTime());
}
수확량
{"epochTime":1506432517242}
2017-09-26T13:28:37.242Z