Spring Boot의 JSON Java 8 LocalDateTime 형식


112

Spring Boot Application에서 Java 8 LocalDateTime을 형식화하는 데 작은 문제가 있습니다. '정상'날짜에는 문제가 없지만 LocalDateTime 필드는 다음과 같이 변환됩니다.

"startDate" : {
    "year" : 2010,
    "month" : "JANUARY",
    "dayOfMonth" : 1,
    "dayOfWeek" : "FRIDAY",
    "dayOfYear" : 1,
    "monthValue" : 1,
    "hour" : 2,
    "minute" : 2,
    "second" : 0,
    "nano" : 0,
    "chronology" : {
      "id" : "ISO",
      "calendarType" : "iso8601"
    }
  }

다음과 같이 변환하고 싶습니다.

"startDate": "2015-01-01"

내 코드는 다음과 같습니다.

@JsonFormat(pattern="yyyy-MM-dd")
@DateTimeFormat(iso = DateTimeFormat.ISO.TIME)
public LocalDateTime getStartDate() {
    return startDate;
}

그러나 위의 주석 중 하나가 작동하지 않고 날짜가 계속 위와 같은 형식으로 지정됩니다. 제안을 환영합니다!

답변:


135

업데이트 : Spring Boot 2.x는 더 이상이 구성이 필요하지 않습니다. 여기에 더 최신 답변을 썼습니다 .


(이것은 Spring Boot 2.x 이전에 수행하는 방법이며 이전 버전의 Spring Boot에서 작업하는 사람들에게 유용 할 수 있습니다.)

나는 마침내 여기에서 그것을하는 방법을 찾았 습니다. 이를 수정하려면 다른 종속성이 필요했습니다.

compile("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.4.0")

이 종속성을 포함함으로써 Spring은 여기에 설명 된대로 자동으로 변환기를 등록합니다 . 그런 다음 application.properties에 다음을 추가해야합니다.

spring.jackson.serialization.write_dates_as_timestamps=false

이렇게하면 올바른 변환기가 사용되며 날짜는 다음 형식으로 인쇄됩니다. 2016-03-16T13:56:39.492

주석은 날짜 형식을 변경하려는 경우에만 필요합니다.


24
- 다음과 같은 주석을 포함한 아마 가치가 @JsonSerialize(using = LocalDateTimeSerializer.class)...
닉 Grealy

3
application.properties@patelb 답변에서 제안한 것처럼 항목을 사용하는 것이 더 좋습니다 .
membersound

작동하지 않는. 그러나 patelib의 대답은 즉시 작동합니다!
Mykhaylo Kopytonenko

참고로 @JsonSerializeNick이 언급 한 주석이 필요 했습니다.
pennstatephil

92

com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.6.1종속성을 추가하고 다음 형식으로 날짜를 가져 오기 시작했습니다.

"birthDate": [
    2016,
    1,
    25,
    21,
    34,
    55
  ]

내가 원했던 것은 아니지만 점점 더 가까워졌습니다. 그런 다음 다음을 추가했습니다.

spring.jackson.serialization.write_dates_as_timestamps=false

필요한 올바른 형식을 제공하는 application.properties 파일에.

"birthDate": "2016-01-25T21:34:55"

2
jackson-datatype-jsr310종속성을 포함 할 때 즉시 작업했습니다 . 이것은 받아 들여진 대답이어야합니다.
membersound

6
참고로 다음을 사용하여 ObjectMapper를 구성하는 경우 Java 구성을 통해 application.properties 부분을 수행 할 수 있습니다.mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
justin

31

여기는 maven에 있으며 속성이 있으므로 봄 부팅 업그레이드 사이에서 살아남을 수 있습니다.

<dependency>
        <groupId>com.fasterxml.jackson.datatype</groupId>
        <artifactId>jackson-datatype-jsr310</artifactId>
        <version>${jackson.version}</version>
</dependency>

1
- 다음과 같은 주석을 포함한 아마 가치 : @NickGrealy 주석이 솔루션을 사용@JsonSerialize(using = LocalDateTimeSerializer.class)
HairOfTheDog

19

1) 의존성

 compile group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-jsr310', version: '2.8.8' 

2) 날짜-시간 형식의 주석.

public class RestObject {

    private LocalDateTime timestamp;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    public LocalDateTime getTimestamp() {
        return timestamp;
    }
}

3) 스프링 구성.

@Configuration
public class JacksonConfig {

    @Bean
    @Primary
    public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
        System.out.println("Config is starting.");
        ObjectMapper objectMapper = builder.createXmlMapper(false).build();
        objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        return objectMapper;
    }
}

2
정말 고마워. @JsonFormat은 나를 위해 그것을 해결 한 것입니다. 위의 솔루션 중 어느 것도 어떤 이유로 저에게 효과가 없었습니다
theprogrammer

7

원하는 형식으로 변환하고 모든 LocalDateTime 데이터 유형에 적용 할 수있는 또 다른 솔루션을 찾았으며 모든 LocalDateTime 데이터 유형 위에 @JsonFormat을 지정할 필요가 없습니다. 먼저 종속성을 추가하십시오.

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
</dependency>

다음 빈을 추가하십시오.

@Configuration
public class Java8DateTimeConfiguration {
    /**
     * Customizing
     * http://docs.spring.io/spring-boot/docs/current/reference/html/howto-spring-mvc.html
     *
     * Defining a @Bean of type Jackson2ObjectMapperBuilder will allow you to customize both default ObjectMapper and XmlMapper (used in MappingJackson2HttpMessageConverter and MappingJackson2XmlHttpMessageConverter respectively).
     */
    @Bean
    public Module jsonMapperJava8DateTimeModule() {
        val bean = new SimpleModule();

        bean.addDeserializer (ZonedDateTime.class, new JsonDeserializer<ZonedDateTime>() {
            @Override
            public ZonedDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
                return ZonedDateTime.parse(jsonParser.getValueAsString(), DateTimeFormatter.ISO_ZONED_DATE_TIME);
            }
        });

        bean.addDeserializer(LocalDateTime.class, new JsonDeserializer<LocalDateTime>() {
            @Override
            public LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
                return LocalDateTime.parse(jsonParser.getValueAsString(), DateTimeFormatter.ISO_LOCAL_DATE_TIME);
            }
        });

        bean.addSerializer(ZonedDateTime.class, new JsonSerializer<ZonedDateTime>() {
            @Override
            public void serialize(
                    ZonedDateTime zonedDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
                    throws IOException {
                jsonGenerator.writeString(DateTimeFormatter.ISO_ZONED_DATE_TIME.format(zonedDateTime));
            }
        });

        bean.addSerializer(LocalDateTime.class, new JsonSerializer<LocalDateTime>() {
            @Override
            public void serialize(
                    LocalDateTime localDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
                    throws IOException {
                jsonGenerator.writeString(DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(localDateTime));
            }
        });

        return bean;
    }
}

구성 파일에 다음을 추가하십시오.

@Import(Java8DateTimeConfiguration.class)

이것은 Spring에서 만든 objectMapper를 사용하는 한 모든 속성 LocalDateTime 및 ZonedDateTime을 직렬화 및 역 직렬화합니다.

ZonedDateTime의 형식은 "2017-12-27T08 : 55 : 17.317 + 02 : 00 [Asia / Jerusalem]"(LocalDateTime) : "2017-12-27T09 : 05 : 30.523"입니다.


예상대로 val bean을 SimpleModule로 대체해야합니다. bean = new SimpleModule ();
Abhishek Galoda

?이 자바 9인가
다니엘 다이

@DanielDai이 자바 8 인
아이다 미트

@Abhi, SimpleModule확장 Module. Module추상입니다. val bean = new SimpleModule(); 완벽하게 작동합니다.
Ida Amit

SpringBoot 버전 1.5.3.RELEASE의 경우 jackson-datatype-jsr310 종속성을 추가 할 필요가 없습니다.
Moon13 2018-04-24

7

이 답변을 저에게도 상기시켜줍니다.

나는 여기에 몇 가지 답변을 결합했으며 결국에는 이와 같은 작업을 수행했습니다. (SpringBoot 1.5.7 및 Lombok 1.16.16을 사용하고 있습니다)

@Data
public Class someClass {

   @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
   @JsonSerialize(using = LocalDateTimeSerializer.class)
   @JsonDeserialize(using = LocalDateTimeDeserializer.class)
   private LocalDateTime someDate;

}

1
DateTimeFormat및 기타에 대한 가져 오기를 추가 할 수 있습니다.
prayagupd

4

이것은 잘 작동합니다.

종속성을 추가하십시오.

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jdk8</artifactId>
</dependency>

주석을 추가하십시오.

@JsonFormat(pattern="yyyy-MM-dd")

이제 올바른 형식을 가져와야합니다.

객체 매퍼를 사용하려면 JavaTime을 등록해야합니다.

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());

1

이미 언급했듯이 spring-boot는 필요한 모든 것을 가져올 것입니다 (웹 및 webflux 스타터 모두).

하지만 더 좋은 점은 모듈을 직접 등록 할 필요가 없다는 것입니다. 봐 여기 . 내부적으로 @SpringBootApplication사용 하기 때문에 자동으로 컨텍스트에 추가됩니다. 이제 내부를 보면 다음이 표시됩니다.@EnableAutoConfigurationJacksonAutoConfigurationJacksonAutoConfiguration

    private void configureModules(Jackson2ObjectMapperBuilder builder) {
        Collection<Module> moduleBeans = getBeans(this.applicationContext,
                Module.class);
        builder.modulesToInstall(moduleBeans.toArray(new Module[0]));
    }

이 친구 는 초기화 과정에서 호출되고 클래스 경로에서 찾을 수있는 모든 모듈을 가져옵니다. (나는 Spring Boot 2.1을 사용합니다)


1

Springboot 2.0.6을 사용하고 있으며 어떤 이유로 앱 yml 변경이 작동하지 않았습니다. 또한 더 많은 요구 사항이있었습니다.

나는 ObjectMapper를 만들고 Primary로 표시하려고 시도했지만 Spring Boot는 이미 jacksonObjectMapper가 Primary로 표시되어 있다고 불평했습니다!

그래서 이것이 제가 한 일입니다. 내부 매퍼를 변경했습니다.

My Serializer와 Deserializer는 특별합니다. 'dd / MM / YYYY'를 처리합니다. 직렬화를 해제하는 동안 3-4 개의 인기있는 형식을 사용하여 LocalDate가 있는지 확인합니다.

@Autowired
ObjectMapper mapper;

@PostConstruct
public ObjectMapper configureMapper() {
    mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);

    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);

    mapper.configure(MapperFeature.ALLOW_COERCION_OF_SCALARS, true);
    mapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true);

    SimpleModule module = new SimpleModule();
    module.addDeserializer(LocalDate.class, new LocalDateDeserializer());
    module.addSerializer(LocalDate.class, new LocalDateSerializer());
    mapper.registerModule(module);

    return mapper;
}

0

@JsonDeserialize(using= LocalDateDeserializer.class) 아래 종속성으로 나를 위해 작동하지 않습니다.

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
    <version> 2.9.6</version>
</dependency>

아래 코드 변환기를 사용하여 날짜를 java.sql.Date.

import javax.persistence.AttributeConverter;
import javax.persistence.Converter;


@SuppressWarnings("UnusedDeclaration")
@Converter(autoApply = true)
public class LocalDateConverter implements AttributeConverter<java.time.LocalDate, java.sql.Date> {


    @Override
    public java.sql.Date convertToDatabaseColumn(java.time.LocalDate attribute) {

        return attribute == null ? null : java.sql.Date.valueOf(attribute);
    }

    @Override
    public java.time.LocalDate convertToEntityAttribute(java.sql.Date dbData) {

        return dbData == null ? null : dbData.toLocalDate();
    }
}

0

간단히 사용 :

@JsonFormat(pattern="10/04/2019")

또는 다음과 같이 원하는대로 패턴을 사용할 수 있습니다. ('-' in place of '/')


이 답변은 이전에 공유되었지만 올바른 구문으로 공유되었습니다.
Erik Pragt 19

0

Spring Boot 2.1.8을 사용하고 있습니다. 나는 수입했다

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-json</artifactId>
</dependency>

여기에는 jackson-datatype-jsr310 이 포함됩니다 .

그런 다음이 주석을 추가해야했습니다.

@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonProperty("date")
LocalDateTime getDate();

그리고 그것은 작동합니다. JSON은 다음과 같습니다.

"date": "2020-03-09 17:55:00"

힌트 : 포함 은 누락 된 spring-boot-starter-json경우에만 필요합니다 spring-boot-starter-web.
judomu
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.