Jackson Mapper를 사용하여 Java 8 LocalDateTime 직렬화 해제
나는 여기 SO에서 serialization과 deserialization 사이의 serialization에 대한 답변과 함께 몇 가지 질문을 읽었다.java.time.LocalDateTime
JSON 자산도 있는데 작동이 안 되는 것 같아요.
원하는 형식으로 날짜를 반환하도록 Spring Boot Application을 설정할 수 있었습니다.(YYY-MM-dd HH:mm
JSON에서 이 형식의 값을 받아들이는 데 문제가 있습니다.
지금까지 제가 한 일은 다음과 같습니다.
maven 의존 관계 추가:jsr310
:
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
명시된jsr310
내 주요 수업에서:
@EntityScan(basePackageClasses = { App.class, Jsr310JpaConverters.class })
타임스탬프로서의 시리얼화를 무효로 했다.application.properties
:
spring.jackson.serialization.write_dates_as_timestamps=false
다음은 datetime에 대한 엔티티 매핑입니다.
@Column(name = "start_date")
@DateTimeFormat(iso = DateTimeFormat.ISO.TIME)
@JsonFormat(pattern = "YYYY-MM-dd HH:mm")
private LocalDateTime startDate;
데이터베이스에 이 날짜를 TIMESTAMP 형식으로 저장합니다.2016-12-01T23:00:00+00:00
.
컨트롤러를 통해 이 엔티티에 액세스하면 올바른 startDate 형식의 JSON이 반환됩니다.게시물을 올리려고 할 때, 그리고 역직렬화하려고 할 때,YYYY-MM-dd HH:mm
포맷은 다음과 같은 예외가 있습니다.
{
"timestamp": "2016-10-30T14:22:25.285+0000",
"status": 400,
"error": "Bad Request",
"exception": "org.springframework.http.converter.HttpMessageNotReadableException",
"message": "Could not read document: Can not deserialize value of type java.time.LocalDateTime from String \"2017-01-01 20:00\": Text '2017-01-01 20:00' could not be parsed: Unable to obtain LocalDateTime from TemporalAccessor: {MonthOfYear=1, WeekBasedYear[WeekFields[SUNDAY,1]]=2017, DayOfMonth=1},ISO resolved to 20:00 of type java.time.format.Parsed\n at [Source: java.io.PushbackInputStream@679a734d; line: 6, column: 16] (through reference chain: com.gigsterous.api.model.Event[\"startDate\"]); nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Can not deserialize value of type java.time.LocalDateTime from String \"2017-01-01 20:00\": Text '2017-01-01 20:00' could not be parsed: Unable to obtain LocalDateTime from TemporalAccessor: {MonthOfYear=1, WeekBasedYear[WeekFields[SUNDAY,1]]=2017, DayOfMonth=1},ISO resolved to 20:00 of type java.time.format.Parsed\n at [Source: java.io.PushbackInputStream@679a734d; line: 6, column: 16] (through reference chain: com.gigsterous.api.model.Event[\"startDate\"])",
"path": "/api/events"
}
이 주제에 대해 많은 답이 있다는 것을 알지만, 그것들을 따라가고 몇 시간 동안 시도해도 내가 무엇을 잘못하고 있는지 알아내는 데 도움이 되지 않았기 때문에, 누군가가 내가 무엇을 놓치고 있는지를 지적해 주었으면 좋겠다.이에 대한 의견을 주셔서 감사합니다!
편집: 프로세스와 관련된 모든 클래스는 다음과 같습니다.
저장소:
@Repository
public interface EventRepository extends PagingAndSortingRepository<Event, Long> {
}
컨트롤러:
@RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Event> createEvent(@RequestBody Event event) {
return new ResponseEntity<>(eventRepo.save(event), HttpStatus.CREATED);
}
JSON 요청 유료:
{
"name": "Test",
"startDate": "2017-01-01 20:00"
}
이벤트:
@Entity
@Table(name = "events")
@Getter
@Setter
public class Event {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "event_id")
private long id;
@Column(name = "name")
private String name;
@Column(name = "start_date")
@DateTimeFormat(iso = DateTimeFormat.ISO.TIME)
@JsonFormat(pattern = "YYYY-MM-dd HH:mm")
private LocalDateTime startDate;
}
전달 중인 날짜 시간이 ISO 로컬 날짜 시간 형식이 아닙니다.
로 변경하다
@Column(name = "start_date")
@DateTimeFormat(iso = DateTimeFormatter.ISO_LOCAL_DATE_TIME)
@JsonFormat(pattern = "YYYY-MM-dd HH:mm")
private LocalDateTime startDate;
'2011-12-03T10:15:30' 형식의 날짜 문자열을 전달합니다.
그러나 커스텀 포맷을 전달하려면 올바른 포맷터를 지정하기만 하면 됩니다.
로 변경하다
@Column(name = "start_date")
@DateTimeFormat(iso = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"))
@JsonFormat(pattern = "YYYY-MM-dd HH:mm")
private LocalDateTime startDate;
당신의 문제는 @DateTimeFormat이 전혀 효과가 없다는 것입니다.잭슨은 탈직렬화를 하고 있고 스프링 주석에 대해 아무것도 모르기 때문에 스프링 주석은 탈직렬화 컨텍스트에서 스캔할 수 없습니다.
또는 Java 타임모듈을 등록하면서 포메터를 설정해 볼 수도 있습니다.
LocalDateTimeDeserializer localDateTimeDeserializer = new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
module.addDeserializer(LocalDateTime.class, localDateTimeDeserializer);
여기 제대로 작동하는 탈염제를 사용한 테스트 케이스입니다.Date Time Format 주석을 완전히 삭제해 보십시오.
@RunWith(JUnit4.class)
public class JacksonLocalDateTimeTest {
private ObjectMapper objectMapper;
@Before
public void init() {
JavaTimeModule module = new JavaTimeModule();
LocalDateTimeDeserializer localDateTimeDeserializer = new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
module.addDeserializer(LocalDateTime.class, localDateTimeDeserializer);
objectMapper = Jackson2ObjectMapperBuilder.json()
.modules(module)
.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.build();
}
@Test
public void test() throws IOException {
final String json = "{ \"date\": \"2016-11-08 12:00\" }";
final JsonType instance = objectMapper.readValue(json, JsonType.class);
assertEquals(LocalDateTime.parse("2016-11-08 12:00",DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm") ), instance.getDate());
}
}
class JsonType {
private LocalDateTime date;
public LocalDateTime getDate() {
return date;
}
public void setDate(LocalDateTime date) {
this.date = date;
}
}
몇 년 동안 잘못된 문자 대소문자를 사용하셨습니다.
@JsonFormat(pattern = "YYYY-MM-dd HH:mm")
다음 항목이어야 합니다.
@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
이 변경으로 모든 것이 예상대로 작동하고 있습니다.
이 방법은 효과가 있었습니다.
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ", shape = JsonFormat.Shape.STRING)
private LocalDateTime startDate;
갱신:
변경 내용:
@Column(name = "start_date")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm", iso = ISO.DATE_TIME)
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm")
private LocalDateTime startDate;
JSON 요청:
{
"startDate":"2019-04-02 11:45"
}
코드에는 다음 두 가지 문제가 있습니다.
1. 잘못된 타입의 사용
LocalDateTime
는 타임존을 지원하지 않습니다.아래는 java.time 타입의 개요이며, date-time 문자열과 일치하는 타입을 확인할 수 있습니다.2016-12-01T23:00:00+00:00
OffsetDateTime
이 「」이기 입니다.+00:00
.
선언을 다음과 같이 변경합니다.
private OffsetDateTime startDate;
2. 잘못된 형식의 사용
포맷에는 다음 두 가지 문제가 있습니다.
- '어울리다'를 써야 요.
y
연령)이 아닌 ()Y
(전년대비).자세한 내용은 이 토론에서 확인하십시오.사실, 나는 당신이 그것을 사용하는 것을 추천한다.u
신년(연식)이 아닌 (y
(연령)자세한 내용은 이 답변을 참조하십시오. - '어울리다'를 써야 요.
XXX
★★★★★★★★★★★★★★★★★」ZZZZZ
즉,은 프프부부부 should should should, 를를들음음음음음, 음음음음음음음음음음음음 for for for 이다.uuuu-MM-dd'T'HH:m:ssXXX
.
의 매뉴얼 페이지를 확인합니다.DateTimeFormatter
이러한 기호/문자에 대한 자세한 내용은 를 참조하십시오.
데모:
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
String strDateTime = "2019-10-21T13:00:00+02:00";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:m:ssXXX");
OffsetDateTime odt = OffsetDateTime.parse(strDateTime, dtf);
System.out.println(odt);
}
}
출력:
2019-10-21T13:00+02:00
최신 날짜 API에 대한 자세한 내용은 Trail: Date Time에서 확인하십시오.
Json Serializer를 구현할 수 있습니다.
참조:
그게 네 특질이야
@JsonProperty("start_date")
@JsonFormat("YYYY-MM-dd HH:mm")
@JsonSerialize(using = DateSerializer.class)
private Date startDate;
이 방법으로 커스텀클래스를 구현합니다.
public class DateSerializer extends JsonSerializer<Date> implements ContextualSerializer<Date> {
private final String format;
private DateSerializer(final String format) {
this.format = format;
}
public DateSerializer() {
this.format = null;
}
@Override
public void serialize(final Date value, final JsonGenerator jgen, final SerializerProvider provider) throws IOException {
jgen.writeString(new SimpleDateFormat(format).format(value));
}
@Override
public JsonSerializer<Date> createContextual(final SerializationConfig serializationConfig, final BeanProperty beanProperty) throws JsonMappingException {
final AnnotatedElement annotated = beanProperty.getMember().getAnnotated();
return new DateSerializer(annotated.getAnnotation(JsonFormat.class).value());
}
}
사후 결과 후에 시험해 보세요.
이것은 나에게 효과가 있었다:
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.format.annotation.DateTimeFormat.ISO;
@Column(name="end_date", nullable = false)
@DateTimeFormat(iso = ISO.DATE_TIME)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
private LocalDateTime endDate;
나한테는 효과가 있어.
@Column(name = "lastUpdateTime")
@DateTimeFormat(iso = ISO.DATE_TIME,pattern = "yyyy-MM-dd HH:mm:ss" )
@JsonIgnore
JSON은 이 JSON에서 할 수 있습니다.{ "pickupDate":"2014-01-01T00:00:00" }
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
@JsonSerialize(using = LocalDateTimeSerializer.class)
private LocalDateTime pickupDate;
언급URL : https://stackoverflow.com/questions/40327970/deserialize-java-8-localdatetime-with-jacksonmapper
'programing' 카테고리의 다른 글
스프링 부트를 사용하지 않고 스프링 휴식 서비스 생성 (0) | 2023.03.06 |
---|---|
Oracle 쿼리에서 문자열의 처음 두 문자를 가져오려면 어떻게 해야 합니까? (0) | 2023.03.06 |
org.disc.inna.disc.discClientAbortException : java.io 。IOException: APR 오류: -32 (0) | 2023.03.06 |
AngularJS 지시적 워치 유효성 (0) | 2023.03.06 |
ng-show/ng-hide에서 Angular 애니메이션 발생 방지 (0) | 2023.03.06 |