1
votes

Comment activer la fonctionnalité 'ALLOW_NUMERIC_LEADING_ZEROS' pour autoriser les zéros non significatifs dans le corps de la requête JSON?

Conformément à la spécification JSON, je suis conscient que les zéros non significatifs ne sont pas autorisés dans les entiers dans JSON. Mais selon la documentation de Jackson, il existe une propriété dans la bibliothèque Jackson, à savoir ALLOW_NUMERIC_LEADING_ZEROS qui, lorsqu'elle est activée, ne lève pas d'exceptions lorsque des zéros non significatifs sont trouvés.

J'ai activé la propriété ALLOW_NUMERIC_LEADING_ZEROS code > en définissant la propriété suivante et j'obtiens toujours une erreur: Les zéros non significatifs ne sont pas autorisés .

/**
 * Method called when we have seen one zero, and want to ensure
 * it is not followed by another
 */
private final int _verifyNoLeadingZeroes() throws IOException
{
    // Ok to have plain "0"
    if (_inputPtr >= _inputEnd && !_loadMore()) {
        return INT_0;
    }
    int ch = _inputBuffer[_inputPtr] & 0xFF;
    // if not followed by a number (probably '.'); return zero as is, to be included
    if (ch < INT_0 || ch > INT_9) {
        return INT_0;
    }
    // [JACKSON-358]: we may want to allow them, after all...
    if (!isEnabled(Feature.ALLOW_NUMERIC_LEADING_ZEROS)) {
        reportInvalidNumber("Leading zeroes not allowed");
    }

    ...
}

Journaux pertinents:

@Autowired
private ObjectMapper objectMapper;

@PostMapping(path = "random_path", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Object> fun123( @RequestBody RandomClass obj) throws Exception {

    log.info(" isEnabled = " + objectMapper.getFactory().isEnabled(JsonParser.Feature.ALLOW_NUMERIC_LEADING_ZEROS));
    log.info(" isEnabled = " + objectMapper.isEnabled(JsonParser.Feature.ALLOW_NUMERIC_LEADING_ZEROS));

    /*
        When correct request is given i.e. no leading zeroes in json body , then this function is successfully executed and
        output is true for above two statements  => i.e. feature 'ALLOW_NUMERIC_LEADING_ZEROS' is enabled.

        When leading zeroes are present in json request body, this function is not executed as an exception 'HttpMessageNotReadableException'
        is generated with error message 'Invalid numeric value: Leading zeroes not allowed'
    */

  ....
}

J'ai vérifié si la propriété ALLOW_NUMERIC_LEADING_ZEROS a été activée ou non en exécutant le code suivant:

Caused by: com.fasterxml.jackson.core.JsonParseException: Invalid numeric value: Leading zeroes not allowed
at [Source: (PushbackInputStream); line: 8, column: 17]
    at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1804) ~[jackson-core-2.9.4.jar:2.9.4]
    at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:663) ~[jackson-core-2.9.4.jar:2.9.4]
    at com.fasterxml.jackson.core.base.ParserMinimalBase.reportInvalidNumber(ParserMinimalBase.java:539) ~[jackson-core-2.9.4.jar:2.9.4]
    at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._verifyNoLeadingZeroes(UTF8StreamJsonParser.java:1489) ~[jackson-core-2.9.4.jar:2.9.4]
    at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._parsePosNumber(UTF8StreamJsonParser.java:1341) ~[jackson-core-2.9.4.jar:2.9.4]
    at com.fasterxml.jackson.core.json.UTF8StreamJsonParser.nextFieldName(UTF8StreamJsonParser.java:1025) ~[jackson-core-2.9.4.jar:2.9.4]
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:376) ~[jackson-databind-2.9.4.jar:2.9.4]
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159) ~[jackson-databind-2.9.4.jar:2.9.4]
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:127) ~[jackson-databind-2.9.4.jar:2.9.4]
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:369) ~[jackson-databind-2.9.4.jar:2.9.4]
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159) ~[jackson-databind-2.9.4.jar:2.9.4]
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4001) ~[jackson-databind-2.9.4.jar:2.9.4]
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3072) ~[jackson-databind-2.9.4.jar:2.9.4]
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:235) ~[spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    ... 63 more

Selon code de UTF8StreamJsonParser.java , lorsque cette propriété est activée, l'exception n'aurait pas dû se produire, mais je ne sais pas pourquoi cela se produit !! Avez-vous une idée de la raison de cela?

Code pertinent de UTF8StreamJsonParser.java :

spring.jackson.parser.ALLOW_NUMERIC_LEADING_ZEROS=true

Version de la bibliothèque Jackson utilisée: 2.9.4


0 commentaires

4 Réponses :


0
votes

Ceci est probablement dû au fait que ObjectMapper utilisé par Spring Endpoint est configuré différemment du mappeur injecté dans le champ. Pourquoi c'est que je ne peux pas dire - peut-être que la liste des utilisateurs de Spring pourrait vous aider.


1 commentaires

Merci d'avoir regarder ceci. Vous avez raison de dire que le mappeur injecté utilisé ci-dessus est différent de celui utilisé par Spring MVC en interne. J'ai vérifié cela en remplaçant la fonction configureMessageConverters de la classe WebMvcConfigurationSupport et en vérifiant les convertisseurs qu'elle ajoute par défaut. Je ne sais pas non plus pourquoi cela se passait! J'ai dû activer la propriété en accédant au convertisseur dans la fonction configureMessageConverters .



0
votes

MappingJackson2HttpMessageConverter utilise par défaut la classe Jackson2ObjectMapperBuilder pour créer une nouvelle instance de la classe ObjectMapper . Pour remplacer et utiliser ObjectMapper à partir du conteneur, nous devons remplacer le convertisseur JSON :

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

import java.util.List;

@Configuration
public class JacksonMvcConfiguration extends WebMvcConfigurationSupport {

    @Autowired
    private ObjectMapper objectMapper;

    public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        converter.setObjectMapper(objectMapper);

        return converter;
    }

    @Override
    protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(mappingJackson2HttpMessageConverter());
        super.configureMessageConverters(converters);
    }
}

Voir Personnalisation des HttpMessageConverters avec Spring Boot et Spring MVC . Depuis, vous devriez pouvoir analyser les nombres avec des zéros non significatifs.


4 commentaires

Eh bien, je voulais utiliser le convertisseur utilisé par Spring MVC, pas le convertisseur personnalisé. J'ai donc remplacé la fonction configureMessageConverters (comme vous l'avez fait ci-dessus), ajouté les convertisseurs par défaut en appelant l'une des fonctions internes et activé la propriété en accédant à la liste des convertisseurs .


@user, j'ai testé mon exemple en utilisant Spring Boot . Il semble que MappingJackson2HttpMessageConverter n'utilise pas par défaut ObjectMapper créé par le conteneur avec une configuration mise à jour. Nous devons le configurer explicitement pour les convertisseurs MVC . Si vous pensez que ma réponse vous a aidé d'une manière ou d'une autre, votez pour.


J'ai observé que le problème avec la configuration explicite des convertisseurs en remplaçant les classes configuration est que Spring MVC ne fait plus la configuration automatique lors de l'initialisation. On peut avoir besoin de s'occuper de tout cela. Par exemple: dans le code ci-dessus (votre), tous les autres convertisseurs par défaut ne seront pas ajoutés à la liste.


@user, consultez cette réponse Comment configurer MappingJacksonHttpMessageConverter en utilisant l'annotation de printemps -basée sur la configuration? et notez "appel à addDefaultHttpMessageConverters ()".



0
votes

Mettez simplement la propriété suivante sur votre fichier application.properties

spring.http.converters.preferred-json-mapper=jackson

Vous pouvez définir jackson comme convertisseur par défaut en suivant la propriété si elle n'est pas définie par défaut

XXX


0 commentaires

0
votes

Juste un petit mot pour les personnes qui rencontrent ce problème et qui recherchent une nouvelle solution de travail:

  1. Importez la dernière version de quickxml jackson dans maven (2.11.0 à partir d'aujourd'hui):

    com.fasterxml.jackson.dataformat jackson-dataformat-xml 2.11.0

  2. Créez l'objet mappeur:

    ObjectMapper objectMapper = new ObjectMapper ();

  3. Autoriser les zéros non significatifs pour les nombres (la version non obsolète):

    objectMapper.enable(JsonReadFeature.ALLOW_LEADING_ZEROS_FOR_NUMBERS.mappedFeature());

importations utilisées :

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.json.JsonReadFeature;

Gardez à l'esprit que cela réduira les 0 en tête. Si vous souhaitez les conserver, votre valeur json ne doit pas être numérique.


0 commentaires