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"])

6voto

Mircea Stanciu Punkte 3399

Dies ist nur ein Beispiel, wie man es in einem Modultest verwendet, den ich gehackt habe, um dieses Problem zu debuggen. Die Schlüsselzutaten sind

  • mapper.registerModule(new JavaTimeModule());
  • Maven-Abhängigkeit von jackson-datatype-jsr310

Code:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.testng.Assert;
import org.testng.annotations.Test;

import java.io.IOException;
import java.io.Serializable;
import java.time.Instant;

class Mumu implements Serializable {
    private Instant from;
    private String text;

    Mumu(Instant from, String text) {
        this.from = from;
        this.text = text;
    }

    public Mumu() {
    }

    public Instant getFrom() {
        return from;
    }

    public String getText() {
        return text;
    }

    @Override
    public String toString() {
        return "Mumu{" +
                "from=" + from +
                ", text='" + text + '\'' +
                '}';
    }
}
public class Scratch {

    @Test
    public void JacksonInstant() throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new JavaTimeModule());

        Mumu before = new Mumu(Instant.now(), "before");
        String jsonInString = mapper.writeValueAsString(before);

        System.out.println("-- BEFORE --");
        System.out.println(before);
        System.out.println(jsonInString);

        Mumu after = mapper.readValue(jsonInString, Mumu.class);
        System.out.println("-- AFTER --");
        System.out.println(after);

        Assert.assertEquals(after.toString(), before.toString());
    }

}

6voto

zenuve Punkte 81

Für diejenigen, die nach einer Lösung für Version ES-8 und Spring Boot:3.0 suchen

Erstellen Sie eine Konfigurationsdatei, die ElasticsearchConfiguration erweitert und clientConfiguration und elasticsearchClient-Erstellung überschreibt.

Injecten Sie während der elasticsearchClient-Erstellung Ihren eigenen objectMapper, der konfiguriert ist, um das Java 8-Zeitmodul zu verwenden, welches den Standard objectMapper überschreibt.

@Override
public ClientConfiguration clientConfiguration() {
    return ClientConfiguration.builder()
            .connectedTo( +":"+ )
            .usingSsl()
            .withBasicAuth(, )
            .build();
}

@Override
public ElasticsearchClient elasticsearchClient(RestClient restClient) {
    Assert.notNull(restClient, "restClient darf nicht null sein");

    // Java8-Zeitmodul erstellen
    JavaTimeModule module = new JavaTimeModule();
    module.addSerializer(new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DateFormat.date_time_no_millis.getPattern())));

    // Modul mit objectMapper registrieren
    ObjectMapper objectMapper=new ObjectMapper()
            .registerModule(module);

    // Datumzeit in ISO-8601 konvertieren
    objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);

    // Eigenen jsonpMapper erstellen 
    JsonpMapper jsonpMapper=new JacksonJsonpMapper(objectMapper);

    // Transport mit einem Jackson-Mapper erstellen
    ElasticsearchTransport transport = new RestClientTransport(
            restClient, jsonpMapper);

    // Und den API-Client erstellen
    return  new ElasticsearchClient(transport);
}

Für diejenigen, die nach einer Lösung für Version ES-8 und Spring Boot:3.2 suchen

@Override
public ClientConfiguration clientConfiguration() {
    return ClientConfiguration.builder()
            .connectedTo( +":"+ )
            .usingSsl()
            .withBasicAuth(, )
            .build();
}

@Override
public JsonpMapper jsonpMapper() {

     var objectMapper = new ObjectMapper()
                    .registerModule(new JavaTimeModule().addSerializer(new ZonedDateTimeSerializer(DateTimeFormatter.ofPattern(DateFormat.date_time_no_millis.getPattern()))));

    // Datumzeit in ISO-8601 konvertieren, ansonsten wird sie in Epoch konvertiert
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);

    return new JacksonJsonpMapper(objectMapper);
}

Maven-Abhängigkeit:

    com.fasterxml.jackson.datatype
    jackson-datatype-jsr310
    2.14.0

6voto

Siddharth Aadarsh Punkte 131
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
@JsonSerialize(using = LocalDateTimeSerializer.class)
private LocalDateTime createTime;

Dies hat für mich funktioniert.

6voto

Janac Meena Punkte 2377

Wenn Sie dieses Problem aufgrund von GraphQL Java-Tools haben und versuchen, ein Java Instant aus einer Datumsschnur zu marshalen, müssen Sie Ihren SchemaParser so einrichten, dass er einen ObjectMapper mit bestimmten Konfigurationen verwendet:

In Ihrer GraphQLSchemaBuilder-Klasse fügen Sie ObjectMapper ein und fügen Sie diese Module hinzu:

        ObjectMapper objectMapper = 
    new ObjectMapper().registerModule(new JavaTimeModule())
            .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);

und fügen Sie es den Optionen hinzu:

final SchemaParserOptions options = SchemaParserOptions.newOptions()
            .objectMapperProvider(fieldDefinition -> objectMapper)
            .typeDefinitionFactory(new YourTypeDefinitionFactory())
            .build();

Siehe https://github.com/graphql-java-kickstart/graphql-spring-boot/issues/32

4voto

Biju Punkte 37

Für Spring Boot API :

@Configuration
public class JsonConfig {

    @Bean
    public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
        MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
        ObjectMapper mapper = new ObjectMapper();

        mapper.registerModule(new ParameterNamesModule())
                .registerModule(new Jdk8Module())
                .registerModule(new JavaTimeModule());

        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);// Entfernt Wert Eigenschaften
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        jsonConverter.setObjectMapper(mapper);
        return jsonConverter;
    }
}

Folgende Abhängigkeiten importieren:

implementation 'com.fasterxml.jackson.core:jackson-core:2.13.0'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.0'
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.0'

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