382 Stimmen

serialize/deserialize Java 8 Java.time mit Jackson JSON mapper

Wie verwende ich den Jackson JSON-Mapper mit Java 8 LocalDateTime?

org.codehaus.jackson.map.JsonMappingException: Kann den Wert des Typs [einfachen Typs, Klasse java.time.LocalDateTime] nicht aus JSON-String instanziieren; kein einzelner String-Konstruktor/Fabrikmethode vorhanden (durch Verweisreihe: MyDTO["field1"]->SubDTO["date"])

1voto

Muhammad Usman Punkte 797

Wenn jemand Probleme bei der Verwendung von SpringBoot hat, hier ist, wie ich das Problem behoben habe, ohne eine neue Abhängigkeit hinzuzufügen.

In Spring 2.1.3 erwartet Jackson das Datumszeichenfolge 2019-05-21T07:37:11.000 im Format yyyy-MM-dd HH:mm:ss.SSS, um in LocalDateTime deserialisiert zu werden. Stellen Sie sicher, dass die Datumszeichenfolge das Datum und die Uhrzeit mit T und nicht mit Leerzeichen trennt. Sekunden (ss) und Millisekunden(SSS) können weggelassen werden.

@JsonProperty("last_charge_date")
public LocalDateTime lastChargeDate;

1voto

aksh1618 Punkte 1915

Ich wollte die Unterstützung für das DurationStyle-Parsing von Spring ermöglichen, das in Eigenschaftsdateien in meinen benutzerdefinierten Konfigurationsdateien verwendet wird, die mit Jackson deserialisiert werden, um beispielsweise 20s zu Duration PT20S zu serialisieren. Dies habe ich erreicht, indem ich einen benutzerdefinierten Deserializer auf der verwendeten ObjectMapper-Instanz registriert habe:

@Bean("customConfigMapper")
public ObjectMapper customConfigMapper() {
    final ObjectMapper mapper = new ObjectMapper();
    final SimpleModule module = new SimpleModule();
    module.addDeserializer(Duration.class, new SpringDurationStyleDeserializer());
    mapper.registerModule(module);
    return mapper;
}

public static class SpringDurationStyleDeserializer extends JsonDeserializer {
    @Override
    public Duration deserialize(JsonParser jsonParser, DeserializationContext __) throws IOException {
        return Optional.ofNullable(jsonParser.getText()).map(DurationStyle::detectAndParse).orElse(null);
    }
}

1voto

Dinesh Punkte 1
ObjectMapper objectMapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.registerModule(new JavaTimeModule());

Dies hat bei mir funktioniert

0voto

Mykhailo Skliar Punkte 1382

Leider hat die hier vorgeschlagene Lösung in meiner Umgebung nicht funktioniert. Aber um ehrlich zu sein, die Verwendung von Java8-Zeitobjekten als DTOs ist nach allem keine sehr gute Idee.

Ich würde empfehlen, stattdessen benutzerdefinierte DTOs zu erstellen und sich nicht auf instabile Bibliotheken zu verlassen, die nach dem nächsten JDK-Release brechen könnten. Dieser Ansatz entspricht auch den bewährten Praktiken der Anti-Korruptions-Schicht und Adaptermuster.

Hier ist ein Beispiel des DTO:

public class ReportDTO implements Serializable {

    private YearMonthDTO yearMonth;

    public YearMonthDTO getYearMonth() {
        return yearMonth;
    }

    public void setYearMonth(final YearMonthDTO yearMonth) {
        this.yearMonth = yearMonth;
    }

    public void fromYearMonth(final YearMonth yearMonth) {
        this.yearMonth = new YearMonthDTO(yearMonth.getYear(), 
                              yearMonth.getMonthValue());
    }

}

public static class YearMonthDTO {

    private int year;

    private int monthValue;

    public YearMonthDTO() {

    }

    public YearMonthDTO(int year, int monthValue) {
        this.year = year;
        this.monthValue = monthValue;
    }

    public int getYear() {
        return year;
    }

    public void setYear(int year) {
        this.year = year;
    }

    public int getMonthValue() {
        return monthValue;
    }

    public void setMonthValue(int monthValue) {
        this.monthValue = monthValue;
    }

}

Es hängt natürlich von Ihrer Situation und dem Arbeitsaufwand ab, den Sie mit dieser Lösung haben. Wie jedes Muster ist diese Lösung nicht auf alle Situationen anwendbar.

In jedem Fall scheint die derzeit beste Antwort nicht mehr zu funktionieren. Ich habe keine anderen Lösungen ausprobiert, aber ich habe beschlossen, mich in meinem einfachen Fall nicht auf Bibliotheken zu verlassen.

0voto

HopeKing Punkte 2877

Für diejenigen, die Spring Boot 2.x verwenden

Es ist nicht notwendig, etwas davon zu tun - Java 8 LocalDateTime wird standardmäßig serialisiert/deserialisiert. Ich musste das alles in 1.x machen, aber mit Boot 2.x funktioniert es nahtlos.

Siehe auch diese Referenz JSON Java 8 LocalDateTime Format in Spring Boot

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X