webentwicklung-frage-antwort-db.com.de

JSON Java 8 LocalDateTime-Format in Spring Boot

Ich habe ein kleines Problem mit der Formatierung einer Java 8 LocalDateTime in meiner Spring Boot-Anwendung. Mit "normalen" Datumsangaben habe ich kein Problem, aber die LocalDateTime-Felder werden wie folgt konvertiert:

"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"
    }
  }

Während ich es gerne in etwas konvertieren möchte:

"startDate": "2015-01-01"

Mein Code sieht so aus:

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

Beide Anmerkungen funktionieren jedoch nicht, das Datum wird wie oben formatiert. Vorschläge willkommen!

84
Erik Pragt

update: Spring Boot 2.x erfordert diese Konfiguration nicht mehr. Ich habe geschrieben eine aktuellere Antwort hier .


(Dies ist die Methode, die vor Spring Boot 2.x ausgeführt wurde. Dies kann für Leute hilfreich sein, die an einer älteren Spring Boot-Version arbeiten.}

Ich fand schließlich hier wie es geht. Um das Problem zu beheben, brauchte ich eine andere Abhängigkeit:

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

Durch die Einbeziehung dieser Abhängigkeit registriert Spring automatisch einen Konverter, wie hier . Danach müssen Sie der Datei application.properties Folgendes hinzufügen:

spring.jackson.serialization.write_dates_as_timestamps=false

Dadurch wird sichergestellt, dass ein korrekter Konverter verwendet wird und Datumsangaben im Format 2016-03-16T13:56:39.492 gedruckt werden.

Anmerkungen werden nur benötigt, wenn Sie das Datumsformat ändern möchten.

108
Erik Pragt

Ich habe die com.fasterxml.jackson.datatype: jackson-datatype-jsr310: 2.6.1 Abhängigkeit hinzugefügt und das Datum im folgenden Format erhalten

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

was ich nicht wollte, aber ich kam näher. Ich habe dann folgendes hinzugefügt

spring.jackson.serialization.write_dates_as_timestamps=false

in die Datei application.properties, die mir das richtige Format gab, das ich brauchte.

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

Hier ist es in Maven, mit der Eigenschaft, so dass Sie zwischen Spring Boot Upgrades bestehen können

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

1) Abhängigkeit

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

2) Annotation mit Datum-Uhrzeit-Format.

public class RestObject {

    private LocalDateTime timestamp;

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

3) Spring Config.

@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;
    }
}
10
Yan Khonski

Ich habe eine andere Lösung gefunden, die Sie in ein beliebiges Format konvertieren können, das auf alle LocalDateTime-Datentypen angewendet werden kann, und Sie müssen @JsonFormat nicht über jedem LocalDateTime-Datentyp angeben. Zuerst müssen Sie die Abhängigkeit hinzufügen: 

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

Fügen Sie die folgende Bohne hinzu: 

@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;
    }
}

fügen Sie in Ihrer Konfigurationsdatei Folgendes hinzu: 

@Import(Java8DateTimeConfiguration.class)

Dadurch werden alle Eigenschaften LocalDateTime und ZonedDateTime serialisiert und deserialisiert, solange Sie den von spring erstellten objectMapper verwenden.

Das Format, das Sie für ZonedDateTime erhalten haben, ist: "2017-12-27T08: 55: 17.317 + 02: 00 [Asia/Jerusalem]" Für LocalDateTime ist: "2017-12-27T09: 05: 30.523"

6
Ida Amit

Das funktioniert gut:

Fügen Sie die Abhängigkeit hinzu:

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

Fügen Sie die Anmerkung hinzu:

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

Nun müssen Sie das richtige Format erhalten.

Um den Object Mapper verwenden zu können, müssen Sie JavaTime registrieren

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

Diese Antwort auch als Erinnerung an mich zu schreiben.

Ich habe hier mehrere Antworten kombiniert und am Ende habe ich mit so etwas gearbeitet .. (Ich benutze SpringBoot 1.5.7 und 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;

}
2
JWiryo

Wie bereits erwähnt, liefert Spring-Boot alles, was Sie brauchen (sowohl für Web- als auch für Webflux-Starter).

Aber was noch besser ist - Sie müssen keine Module selbst registrieren Schauen Sie hier . Da @SpringBootApplication@EnableAutoConfiguration unter der Haube verwendet, bedeutet dies, dass JacksonAutoConfiguration automatisch zum Kontext hinzugefügt wird . Wenn Sie jetzt in JacksonAutoConfiguration schauen, werden Sie Folgendes sehen:

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

Diese Fella wird während des Initialisierungsprozesses aufgerufen und ruft alle Module ab, die sie im Klassenpfad finden kann. (Ich benutze Spring Boot 2.1)

0
yuranos87

@JsonDeserialize(using= LocalDateDeserializer.class) arbeitet für mich nicht mit der unten angegebenen Abhängigkeit.

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

Ich habe den untenstehenden Code-Konverter verwendet, um das Datum in einen Java.sql.Date zu deserialisieren.

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
Ram

Ich verwende Springboot 2.0.6 und aus irgendeinem Grund funktionierten die Änderungen an der App-YML nicht. Und ich hatte auch mehr Anforderungen.

Ich habe versucht, ObjectMapper zu erstellen und als primär zu kennzeichnen, aber spring boot hat sich darüber beschwert, dass ich jacksonObjectMapper bereits als primär gekennzeichnet habe !!

Das habe ich also getan. Ich habe Änderungen am internen Mapper vorgenommen.

Mein Serializer und mein Deserializer sind etwas Besonderes - sie behandeln 'TT/MM/JJJJ'; und während der Deserialisierung - es versucht sein Bestes, 3-4 populäres Format zu verwenden, um sicherzustellen, dass ich etwas LocalDate habe.

@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
Kalpesh Soni

benutze einfach:

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

oder Sie können Muster verwenden, wie Sie möchten, zum Beispiel: ('-' in place of '/')

0
Ashish Dwivedi