1
votes

Spring Boot, définissez la précision datetime à millis dans la réponse REST

J'ai créé une application Web Spring qui propose l'API REST. J'utilise Spring Boot 2.x, Spring Data REST, Spring HATEOAS, Spring JPA, Hibernate 5.3, Mysql.

J'utilise également jackson-datatype-jsr310.

Je travaille avec les dates UTC dans toute l'application et je stocke les dates UTC dans Mysql.

Dans mon bean, les dates sont définies comme suit:

@EnableHypermediaSupport(type = {EnableHypermediaSupport.HypermediaType.HAL})

Tout fonctionne mais lorsque l'API est consommée, les dates sont renvoyées dans ce format:

@Autowired(required = true)
public void configureJackson(ObjectMapper jackson2ObjectMapper) {
    jackson2ObjectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    jackson2ObjectMapper.configure(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS, false);
}

Je souhaite tronquer chaque date / heure de mon application en millisecondes, la date doit donc be:

"validUntil": "2019-11-05T22: 59: 59.999Z"

Dans ma @Configuration, j'utilise un JacksonModule personnalisé:

    @Bean
    public Module customJacksonModule() {
        SimpleModule customJacksonModule = new SimpleModule();
        customJacksonModule.addSerializer(ConstraintViolationException.class, constraintViolationExceptionSerializer());
        customJacksonModule.addSerializer(ValidationException.class, validationExceptionSerializer());
        customJacksonModule.addSerializer(cloud.optix.server.exceptions.ValidationException.class, customValidationExceptionSerializer());  
        return customJacksonModule;
    }

J'ai essayé plusieurs approches mais personne n'a fonctionné jusqu'à présent:

1. Application.properties

J'ai mis spring.jackson.serialization.write-date-timestamps-as-nanoseconds = false dans mon application.propreties

2. ObjectMapper personnalisé

J'ai essayé de modifier les paramètres de objectMapper.

"validUntil" : "2019-11-05T22:59:59.999999Z"

3. Suppression de @EnableHypermediaSupport

    @NotNull
    @Column(nullable = false)
    private Instant validUntil;

Toutes ces actions n'ont pas changé la façon dont la date est renvoyée au client. J'aimerais avoir des conseils pour comprendre / déboguer pourquoi la date n'est pas renvoyée dans le bon format.

Comme note supplémentaire, j'ai trouvé cela dans com.fasterxml.jackson.datatype.jsr310.ser .InstantSerializerBase dans la méthode serialize () Je n'ai ni propriété useNanoseconds , ni formateur par défaut. Cependant, la propriété spring.jackson.serialization.write-dates-as-timestamps dans application.properties a un effet sur le format de la date.

 entrez la description de l'image ici


0 commentaires

3 Réponses :


1
votes

Avez-vous simplement essayé d'annoter votre champ validUntil avec @JsonFormat comme ci-dessous.

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ")
@NotNull
@Column(nullable = false)
private Instant validUntil;


1 commentaires

Cela fonctionne mais je devrais ajouter cette annotation sur tous les champs de mon application. J'aimerais faire quelque chose pour l'ensemble de l'application au niveau de la configuration



1
votes

Vous pouvez configurer votre ObjectMapper pour utiliser un format de date spécifique dans l'application:

jackson2ObjectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSz"));


2 commentaires

J'ai essayé mais cela ne change pas le format dans mon cas.


Cela ne fonctionne pas pour type java.time .



1
votes

Vous devez remplacer InstantSerializer est utilisé par Jackson.

@Configuration
public class JacksonConfig {

    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() {
        return builder -> builder.serializers(new CustomInstantSerializer());
    }

    private static class CustomInstantSerializer extends InstantSerializer {

        private static final DateTimeFormatter UTC_DATE_FORMAT = DateTimeFormatter
                .ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").withZone(ZoneOffset.UTC);

        private CustomInstantSerializer() {
            super(InstantSerializer.INSTANCE, null, UTC_DATE_FORMAT);
        }

    }

}

Vous pouvez mettre la classe JacksonConfig dans la configuration package du projet, par exemple.

De plus, si cela ne fonctionne pas, vérifiez que SpringBoot peut vraiment le trouver. Définissez un point d'arrêt dans le constructeur par défaut de InstantSerializer ou ajoutez-y une journalisation temporelle.


0 commentaires