API에서 오는 날짜 형식이 다음과 같습니다.
"start_time": "2015-10-1 3:00 PM GMT+1:00"
YYYY-DD-MM HH : MM am / pm GMT 타임 스탬프입니다. 이 값을 POJO의 Date 변수에 매핑하고 있습니다. 분명히 변환 오류를 표시합니다.
두 가지를 알고 싶습니다.
- Jackson으로 변환하기 위해 사용해야하는 형식은 무엇입니까? Date가 이것에 적합한 필드 유형입니까?
- 일반적으로 Jackson이 객체 멤버에 매핑하기 전에 변수를 처리하는 방법이 있습니까? 형식 변경, 계산 등
답변
Jackson으로 변환하기 위해 사용해야하는 형식은 무엇입니까? Date가 이것에 적합한 필드 유형입니까?
Date
이에 대한 훌륭한 필드 유형입니다. 다음을 사용하여 JSON 구문 분석 가능을 쉽게 만들 수 있습니다 ObjectMapper.setDateFormat
.
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm a z");
myObjectMapper.setDateFormat(df);
일반적으로 Jackson이 객체 멤버에 매핑하기 전에 변수를 처리하는 방법이 있습니까? 형식 변경, 계산 등
예. JsonDeserializer
예를 들어 확장과 같은 사용자 정의 구현을 포함하여 몇 가지 옵션이 있습니다 JsonDeserializer<Date>
. 이것은 좋은 시작입니다.
답변
Jackson v2.0부터 @JsonFormat 주석을 Object 멤버에서 직접 사용할 수 있습니다.
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm a z")
private Date date;
답변
물론 직렬화 및 역 직렬화라는 자동화 된 방법 이 있으며 특정 주석 ( @JsonSerialize , @JsonDeserialize)으로 정의 할 수 있습니다. 언급 )으로 있습니다.
java.util.Date 및 java.util.Calendar …와 아마도 JodaTime을 모두 사용할 수 있습니다.
역 직렬화 (직렬화가 완벽하게 작동 ) 중에 @JsonFormat 주석이 원하는대로 작동하지 않았습니다 ( 시간대 를 다른 값으로 조정 했습니다).
@JsonFormat(locale = "hu", shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm", timezone = "CET")
@JsonFormat(locale = "hu", shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm", timezone = "Europe/Budapest")
예측 된 결과를 원하면 @JsonFormat 주석 대신 사용자 정의 직렬 변환기 및 사용자 정의 디시리얼라이저를 사용해야합니다. 여기에서 훌륭한 튜토리얼과 솔루션을 찾았습니다.http://www.baeldung.com/jackson-serialize-dates에서 .
Date 필드 에는 예제가 있지만 Calendar 필드에는 필요 하므로 구현은 다음과 같습니다.
시리얼 라이저 클래스 :
public class CustomCalendarSerializer extends JsonSerializer<Calendar> {
public static final SimpleDateFormat FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm");
public static final Locale LOCALE_HUNGARIAN = new Locale("hu", "HU");
public static final TimeZone LOCAL_TIME_ZONE = TimeZone.getTimeZone("Europe/Budapest");
@Override
public void serialize(Calendar value, JsonGenerator gen, SerializerProvider arg2)
throws IOException, JsonProcessingException {
if (value == null) {
gen.writeNull();
} else {
gen.writeString(FORMATTER.format(value.getTime()));
}
}
}
디시리얼라이저 클래스 :
public class CustomCalendarDeserializer extends JsonDeserializer<Calendar> {
@Override
public Calendar deserialize(JsonParser jsonparser, DeserializationContext context)
throws IOException, JsonProcessingException {
String dateAsString = jsonparser.getText();
try {
Date date = CustomCalendarSerializer.FORMATTER.parse(dateAsString);
Calendar calendar = Calendar.getInstance(
CustomCalendarSerializer.LOCAL_TIME_ZONE,
CustomCalendarSerializer.LOCALE_HUNGARIAN
);
calendar.setTime(date);
return calendar;
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
}
위 클래스 의 사용법 :
public class CalendarEntry {
@JsonSerialize(using = CustomCalendarSerializer.class)
@JsonDeserialize(using = CustomCalendarDeserializer.class)
private Calendar calendar;
// ... additional things ...
}
이 구현을 사용하면 직렬화 및 역 직렬화 프로세스를 연속적으로 실행하면 원점 값이 생성됩니다.
@JsonFormat 주석 만 사용하면 deserialization은 라이브러리 내부 표준 시간대 기본 설정 때문에 주석 매개 변수로 변경할 수없는 결과 (Jackson 라이브러리 2.5.3 및 2.6.3 버전에서도 경험 한 결과)가 다른 결과를 낳습니다 .
답변
날짜 시간 형식의 스프링 부트 응용 프로그램에 대한 완벽한 예RFC3339
package bj.demo;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import java.text.SimpleDateFormat;
/**
* Created by BaiJiFeiLong@gmail.com at 2018/5/4 10:22
*/
@SpringBootApplication
public class BarApp implements ApplicationListener<ApplicationReadyEvent> {
public static void main(String[] args) {
SpringApplication.run(BarApp.class, args);
}
@Autowired
private ObjectMapper objectMapper;
@Override
public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX"));
}
}
답변
날짜에 T 및 Z와 같은 문자를 추가하려면
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'")
private Date currentTime;
산출
{
"currentTime": "2019-12-11T11:40:49Z"
}
답변
나를 위해 일하고 있습니다. 스프링 부트.
import com.alibaba.fastjson.annotation.JSONField;
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
산출:
{
"createTime": "2019-06-14 13:07:21"
}
답변
@ miklov-kriven의 매우 유용한 답변을 바탕 으로이 두 가지 추가 고려 사항이 누군가에게 도움이되기를 바랍니다.
(1) serializer와 de-serializer를 동일한 클래스의 정적 내부 클래스로 포함시키는 것이 좋습니다. NB, ThreadD를 사용하여 SimpleDateFormat의 스레드 안전성.
public class DateConverter {
private static final ThreadLocal<SimpleDateFormat> sdf =
ThreadLocal.<SimpleDateFormat>withInitial(
() -> {return new SimpleDateFormat("yyyy-MM-dd HH:mm a z");});
public static class Serialize extends JsonSerializer<Date> {
@Override
public void serialize(Date value, JsonGenerator jgen SerializerProvider provider) throws Exception {
if (value == null) {
jgen.writeNull();
}
else {
jgen.writeString(sdf.get().format(value));
}
}
}
public static class Deserialize extends JsonDeserializer<Date> {
@Overrride
public Date deserialize(JsonParser jp, DeserializationContext ctxt) throws Exception {
String dateAsString = jp.getText();
try {
if (Strings.isNullOrEmpty(dateAsString)) {
return null;
}
else {
return new Date(sdf.get().parse(dateAsString).getTime());
}
}
catch (ParseException pe) {
throw new RuntimeException(pe);
}
}
}
}
(2) 각 개별 클래스 멤버에서 @JsonSerialize 및 @JsonDeserialize 주석을 사용하는 대신 애플리케이션 레벨에서 사용자 정의 직렬화를 적용하여 Jackson의 기본 직렬화를 대체 할 수도 있습니다. 즉, 날짜 유형의 모든 클래스 멤버가 Jackson에 의해 직렬화됩니다. 각 필드에 명시적인 주석없이이 사용자 지정 직렬화를 사용합니다. 예를 들어 Spring Boot를 사용하는 경우 한 가지 방법은 다음과 같습니다.
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public Module customModule() {
SimpleModule module = new SimpleModule();
module.addSerializer(Date.class, new DateConverter.Serialize());
module.addDeserializer(Date.class, new Dateconverter.Deserialize());
return module;
}
}