Jackson을 사용하여 Instant를 ISO8601로 직렬화할 때 강제로 밀리초
제가 사용하는 프로젝트에서 잭슨을 사용한 JSON 연재와 관련하여 몇 가지 질문이 있습니다.Spring Boot 2.0.0.M6
,Spring Framework 5.0.1.RELEASE
그리고.Jackson 2.9.2
.
에서 다음과 같은 잭슨 관련 설정을 구성했습니다.application.properties
:
spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS=false
직렬화는 대부분 필요에 따라 작동합니다.그럼에도 불구하고, 나는 잭슨이 만약 그들이 그렇다면 밀리초를 잘라내는 것처럼 보인다는 것을 알아챘습니다.000
.
테스트 1: 밀리초로 설정된 인스턴트 직렬화000
:
- 다음을 사용하여 인스턴트 필드 초기화
Instant.parse("2017-09-14T04:28:48.000Z")
- 잭슨을 사용하여 일련화
- 출력은 다음과 같습니다.
"2017-09-14T04:28:48Z"
테스트 2: 밀리초가 아닌 일부로 설정된 인스턴트 직렬화000
값:
- 다음을 사용하여 인스턴트 필드 초기화
Instant.parse("2017-09-14T04:28:48.100Z")
- 잭슨을 사용하여 일련화
- 출력은 다음과 같습니다.
"2017-09-14T04:28:48.100Z"
질문:
- 의도적으로 그런 행동을 한 건가요?
- 제가 할 수 있는 일이 있습니까?
000
?
다음 방법을 사용하여 해결합니다.
ObjectMapper objectMapper = new ObjectMapper();
JavaTimeModule module = new JavaTimeModule();
module.addSerializer(Instant.class, new InstantSerializerWithMilliSecondPrecision());
objectMapper.registerModule(module);
또한 Instant Serializer의 경우MilliSecond Precision에서는 다음을 사용했습니다.
public class InstantSerializerWithMilliSecondPrecision extends InstantSerializer {
public InstantSerializerWithMilliSecondPrecision() {
super(InstantSerializer.INSTANCE, false, new DateTimeFormatterBuilder().appendInstant(3).toFormatter());
}
}
이제 인스턴트 직렬화에는 항상 밀리초가 포함됩니다.예: 2019-09-27T02:59:59.000Z
여기에는 이에 대한 Jackson 문제가 열려 있는 것 같습니다*.해당 링크에는 두 가지 해결 방법이 있습니다.
해결 방법 1
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
SimpleModule module = new SimpleModule();
module.addSerializer(ZonedDateTime.class, new JsonSerializer<ZonedDateTime>() {
@Override
public void serialize(ZonedDateTime zonedDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
jsonGenerator.writeString(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZZZ").format(zonedDateTime));
}
});
objectMapper.registerModule(module);
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
해결 방법 2
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(ZonedDateTime.class,
new ZonedDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX")));
ObjectMapper mapper = new ObjectMapper().registerModule(javaTimeModule);
*FasterX를 사용하지 않아 링크가 중단되었습니다.ML/jackson-datatype-jsr310을 jackson-modules-java8로 이동했습니다.https://github.com/FasterXML/jackson-modules-java8/issues/76 을 참조하십시오.
Spring Boot에서 이것을 시도하고 있고 @Gustavo의 대답을 사용하고 싶다면.
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
@Bean
public Module javaTimeModule() {
JavaTimeModule module = new JavaTimeModule();
module.addSerializer(new InstantSerializerWithMilliSecondPrecision());
return module;
}
}
션 캐롤이 언급한 두 가지 해결책 중 어느 것도 저에게는 통하지 않습니다.저는 결국 Instant를 위한 저만의 연재물을 작성하게 됩니다.
final ObjectMapper mapper = new ObjectMapper();
final JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(Instant.class, new KeepMillisecondInstantSerializer());
mapper.registerModule(javaTimeModule);
public class KeepMillisecondInstantSerializer extends JsonSerializer<Instant> {
private final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX")
.withZone(ZoneId.of("UTC"));
@Override
public void serialize(final Instant instant, final JsonGenerator jsonGenerator, final SerializerProvider serializerProvider) throws IOException {
final String serializedInstant = dateTimeFormatter.format(instant);
jsonGenerator.writeString(serializedInstant);
}
}
잭슨은 기본적으로 인스턴트 객체를 직렬화하는 방법을 사용하는 것 같습니다.또한 StackOverflow에서 메서드에 대한 몇 가지 논의를 발견했습니다.
Jackson 라이브러리의 버그를 수정하는 대신 다음과 같은 간단한 해결 방법이 있을 수 있습니다. Timestamp 변수가 있는 POJO 클래스에 문자열 변수를 만듭니다.
private Timestamp createTimeStamp;
private String stringCreateTimeStamp;
타임스탬프 값을 문자열로 캡처:
listOfPojo.forEach(pojo-> {
pojo.setStringCreateTimeStamp(request.getcreateTimeStamp().toString());
});
변환은 https://www.baeldung.com/java-string-to-timestamp 를 참조하십시오.
LocalDateTime 및 ZoneDateTime 클래스에 대한 사용자 지정 직렬화 프로그램을 사용하여 문제를 해결합니다.
API 응답에서 날짜와 시간을 나타내기 위해 이 두 클래스만 사용하기 때문에 제 솔루션은 제게 적합합니다!저는 인스턴트나 날짜를 사용하지 않으니 주의하세요.
@Configuration
class JacksonConfig {
@Bean
fun objectMapper(): ObjectMapper {
val mapper = ObjectMapper()
val javaTimeModule = JavaTimeModule().apply {
addSerializer(LocalDateTime::class.java, KeepMillisecondLocalDateTimeSerializer())
addSerializer(ZonedDateTime::class.java, KeepMillisecondZonedDateTimeSerializer())
}
mapper.registerModule(javaTimeModule)
return mapper
}
class KeepMillisecondZonedDateTimeSerializer : JsonSerializer<ZonedDateTime>() {
private val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX")
@Throws(IOException::class)
override fun serialize(
value: ZonedDateTime,
jsonGenerator: JsonGenerator,
serializerProvider: SerializerProvider?
) {
jsonGenerator.writeString(formatter.format(value))
}
}
class KeepMillisecondLocalDateTimeSerializer : JsonSerializer<LocalDateTime>() {
private val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS")
@Throws(IOException::class)
override fun serialize(
value: LocalDateTime,
jsonGenerator: JsonGenerator,
serializerProvider: SerializerProvider?
) {
jsonGenerator.writeString(formatter.format(value))
}
}
}
언급URL : https://stackoverflow.com/questions/47502158/force-milliseconds-when-serializing-instant-to-iso8601-using-jackson
'source' 카테고리의 다른 글
DispatcherServlet 구성에는 이 핸들러를 지원하는 HandlerAdapter가 포함되어야 합니다. (0) | 2023.07.21 |
---|---|
SQL Developer에서 내보낼 때 SPOOL이 빈 파일을 반환합니다. (0) | 2023.07.21 |
Console Service Discovery를 통한 자동 프록시 서비스 (0) | 2023.07.21 |
판다 데이터 프레임의 사용자 지정 정렬 (0) | 2023.07.16 |
이전 달의 날짜/시간 개체 반환 (0) | 2023.07.16 |