{
"timestamp": "2023-04-11T16:33:28.312+00:00",
"status": 400,
"error": "Bad Request",
"trace": "org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `java.time.LocalDateTime` from String \\"2023-04-10'T'10:48:12\\": Failed to deserialize java.time.LocalDateTime: (java.time.format.DateTimeParseException) Text '2023-04-10'T'10:48:12' could not be parsed at index 10; nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.time.LocalDateTime` from String \\"2023-04-10'T'10:48:12\\": Failed to deserialize java.time.LocalDateTime: (java.time.format.DateTimeParseException) Text '2023-04-10'T'10:48:12' could not be parsed at index 10\\n at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 5, column: 19] (through reference chain: com.techeer.fmstudio.domain.banner.dto.BannerCreateRequest[\\"startedAt\\"])\\n\\tat org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:391)\\n\\tat org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:343)\\n\\tat org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters(AbstractMessageConverterMethodArgumentResolver.java:185)\\n\\tat org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.readWithMessageConverters(RequestResponseBodyMethodProcessor.java:160)\\n\\tat org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:133)\\n\\tat org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:122)\\n\\tat org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:179)\\n\\tat org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:146)\\n\\tat org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)\\n\\tat org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)\\n\\tat org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)\\n\\tat org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)\\n\\tat org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1071)\\n\\tat org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:964)\\n\\tat org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)\\n\\tat org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)\\n\\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:696)\\n\\tat org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)\\n\\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:779)\\n\\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)\\n\\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\\n\\tat org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)\\n\\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\\n\\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\\n\\tat org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)\\n\\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)\\n\\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\\n\\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\\n\\tat org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)\\n\\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)\\n\\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\\n\\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\\n\\tat org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)\\n\\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)\\n\\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\\n\\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\\n\\tat org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:177)\\n\\tat org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)\\n\\tat org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)\\n\\tat org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)\\n\\tat org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)\\n\\tat org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)\\n\\tat org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360)\\n\\tat org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399)\\n\\tat org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)\\n\\tat org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:891)\\n\\tat org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1784)\\n\\tat org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)\\n\\tat org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)\\n\\tat org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)\\n\\tat org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\\n\\tat java.base/java.lang.Thread.run(Thread.java:833)\\nCaused by: com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.time.LocalDateTime` from String \\"2023-04-10'T'10:48:12\\": Failed to deserialize java.time.LocalDateTime: (java.time.format.DateTimeParseException) Text '2023-04-10'T'10:48:12' could not be parsed at index 10\\n at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 5, column: 19] (through reference chain: com.techeer.fmstudio.domain.banner.dto.BannerCreateRequest[\\"startedAt\\"])\\n\\tat com.fasterxml.jackson.databind.exc.InvalidFormatException.from(InvalidFormatException.java:67)\\n\\tat com.fasterxml.jackson.databind.DeserializationContext.weirdStringException(DeserializationContext.java:1991)\\n\\tat com.fasterxml.jackson.databind.DeserializationContext.handleWeirdStringValue(DeserializationContext.java:1219)\\n\\tat com.fasterxml.jackson.datatype.jsr310.deser.JSR310DeserializerBase._handleDateTimeException(JSR310DeserializerBase.java:176)\\n\\tat com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer._fromString(LocalDateTimeDeserializer.java:179)\\n\\tat com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer.deserialize(LocalDateTimeDeserializer.java:81)\\n\\tat com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer.deserialize(LocalDateTimeDeserializer.java:40)\\n\\tat com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:138)\\n\\tat com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:392)\\n\\tat com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:185)\\n\\tat com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:323)\\n\\tat com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4674)\\n\\tat com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3682)\\n\\tat org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:380)\\n\\t... 51 more\\nCaused by: java.time.format.DateTimeParseException: Text '2023-04-10'T'10:48:12' could not be parsed at index 10\\n\\tat java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2052)\\n\\tat java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1954)\\n\\tat java.base/java.time.LocalDateTime.parse(LocalDateTime.java:494)\\n\\tat com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer._fromString(LocalDateTimeDeserializer.java:177)\\n\\t... 60 more\\n",
"message": "JSON parse error: Cannot deserialize value of type `java.time.LocalDateTime` from String \\"2023-04-10'T'10:48:12\\": Failed to deserialize java.time.LocalDateTime: (java.time.format.DateTimeParseException) Text '2023-04-10'T'10:48:12' could not be parsed at index 10; nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.time.LocalDateTime` from String \\"2023-04-10'T'10:48:12\\": Failed to deserialize java.time.LocalDateTime: (java.time.format.DateTimeParseException) Text '2023-04-10'T'10:48:12' could not be parsed at index 10\\n at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 5, column: 19] (through reference chain: com.techeer.fmstudio.domain.banner.dto.BannerCreateRequest[\\"startedAt\\"])",
"path": "/api/v1/banner"
}
package com.techeer.fmstudio.domain.banner.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.techeer.fmstudio.domain.banner.domain.Comment;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
import java.util.List;
@Getter
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class BannerCreateRequest {
@NotBlank(message = "Member Id of banner owner is required")
private Long memberId;
@NotBlank(message = "Banner title is required")
private String title;
@NotBlank(message = "Banner memo is required")
private String memo;
@NotNull(message = "Banner start date is required")
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
// @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
private LocalDateTime startedAt;
@NotNull(message = "Banner end date is required")
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
// @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
private LocalDateTime endAt;
private List<Comment> commentList;
private List<String> imageUrl;
}
[##Image|kage@cjJ6Fc/btr9zOw1ri6/Ry4f62S1IBAh7ewhtZIIfk/img.png|CDM|1.3|{"originWidth":1280,"originHeight":560,"style":"alignCenter"}##]
중간에 T를 넣는 이유는 띄어쓰기로 인해서 값이 잘못 넘어올 수 있기 때문
사용한 date format은 iso 8601 표준을 따름
스프링 부트 서버에서 String을 LocalDateFormat으로 변환하기 보단 어노테이션을 이용해서 컨트롤러 단에 들어오기 전에 변환이 가능함.
주의할 점은 Format 중간에 ‘T’라고 되어 있더라도 따옴표를 추가해선 안됨.
추가하면 역직렬화가 실패함. (위의 오류가 발생한 원인)
또한 Jackson 라이브러리는 Spring Boot Starter web 2.x.x 부터는 기본으로 포함되어 있다.