Comment désérialiser une valeur float avec un localisée séparateur décimal avec Jackson
Le flux d'entrée, je suis d'analyse avec Jackson contient des valeurs de latitude et longitude comme ici:
{
"name": "product 23",
"latitude": "52,48264",
"longitude": "13,31822"
}
Pour une raison quelconque, le serveur utilise des virgules comme séparateur décimal, ce qui produit un InvalidFormatException
. Puisque je ne peux pas changer le serveur format de sortie je voudrais enseigner Jackson ObjectMapper
pour gérer ces cas. Voici le code correspondant:
public static Object getProducts(final String inputStream) {
ObjectMapper objectMapper = new ObjectMapper();
try {
return objectMapper.readValue(inputStream,
new TypeReference<Product>() {}
);
} catch (UnrecognizedPropertyException e) {
e.printStackTrace();
} catch (InvalidFormatException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (JsonParseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
Et voici le POJO:
import com.fasterxml.jackson.annotation.JsonProperty;
public class Product {
@JsonProperty("name")
public String name;
@JsonProperty("latitude")
public float latitude;
@JsonProperty("longitude")
public float longitude;
}
Comment puis-je dire à Jackson que ces valeurs de coordonnées venir avec une version allemande?
Je suppose que une coutume deserializer pour les champs spécifiques comme discuté ici serait la voie à suivre. J'ai rédigé ceci:
public class GermanFloatDeserializer extends JsonDeserializer<Float> {
@Override
public Float deserialize(JsonParser parser, DeserializationContext context)
throws IOException {
//TODO Do some comma magic
return floatValue;
}
}
Puis le POJO devrait ressembler à ceci:
import com.fasterxml.jackson.annotation.JsonProperty;
public class Product {
@JsonProperty("name")
public String name;
@JsonDeserialize(using = GermanFloatDeserializer.class, as = Float.class)
@JsonProperty("latitude")
public float latitude;
@JsonDeserialize(using = GermanFloatDeserializer.class, as = Float.class)
@JsonProperty("longitude")
public float longitude;
}
Ce que vous avez est invalid JSON. Demandez à la personne de fournir le JSON vous fournir des trucs légaux.
Est-il invalide en raison de la
La virgule point décimal n'est pas valide JSON. Vous pouvez aller à json.org et de voir la syntaxe. Il est possible que la virgule apparaît parce que de toute façon votre demande au serveur implique un jeu de paramètres régionaux, et de changer ce qui impliquait locale va résoudre le problème, mais sinon les gens à l'autre bout devrait résoudre le problème.
jslint.com dit qu'il est valide. Cependant, le côté serveur n'est pas sous mon contrôle.
Eh bien, je suppose que c'est valable, parce que ceux sont des chaînes de caractères, pas des nombres. C'est à vous de gérer les chaînes de votre choix. N'a rien à voir avec JSON, en soi. Changement
Est-il invalide en raison de la
,
comme séparateur décimal? Dans le cas où vous signifiait la virgule - c'est quelque chose que j'ai oublié de taper. Je l'ai corrigé.La virgule point décimal n'est pas valide JSON. Vous pouvez aller à json.org et de voir la syntaxe. Il est possible que la virgule apparaît parce que de toute façon votre demande au serveur implique un jeu de paramètres régionaux, et de changer ce qui impliquait locale va résoudre le problème, mais sinon les gens à l'autre bout devrait résoudre le problème.
jslint.com dit qu'il est valide. Cependant, le côté serveur n'est pas sous mon contrôle.
Eh bien, je suppose que c'est valable, parce que ceux sont des chaînes de caractères, pas des nombres. C'est à vous de gérer les chaînes de votre choix. N'a rien à voir avec JSON, en soi. Changement
public float latitude;
à public String latitude;
, etc.OriginalL'auteur JJD | 2014-11-03
Vous devez vous connecter pour publier un commentaire.
Je suis venu avec la solution suivante:
...
Encore je me demande pourquoi je ne pas de travail quand je spécifier la valeur de retour de la classe comme
as = Float.class
que peuvent être trouvés dans la la documentation deJsonDeserialize
. Il se lit comme si je suis censé utiliser l'un ou l'autre mais pas les deux. Que ce soit, les docs affirment également queas =
seront ignorées lors de l'using =
est défini:OriginalL'auteur JJD
Plus générale de la solution que les autres réponses proposées, qui nécessitent l'enregistrement individuel deserializers pour chaque type, est de fournir une mesure
DefaultDeserializationContext
àObjectMapper
.La suite de la mise en œuvre (qui est inspiré par
DefaultDeserializationContext.Impl
) a fonctionné pour moi:Maintenant configurer votre objet mappeur de vos paramètres régionaux:
Si vous utilisez Printemps
RestTemplate
, vous pouvez le configurer pour une utilisationobjectMapper
comme suit:Remarque que la valeur doit être représenté comme une chaîne de caractères dans le document JSON (c'est à dire
{"number": "2,2"}
), depuis par exemple{"number": 2,2}
n'est pas valide JSON et ne parviennent pas à analyser.OriginalL'auteur Halle Knast
Avec tout le respect pour accepté de répondre, il y a un moyen de se débarrasser de ces
@JsonDeserialize
annotations.Vous devez vous inscrire à la coutume deserializer dans le ObjectMapper.
Suivant le tutoriel à partir de site web officiel que vous venez de faire quelque chose comme:
Si vous utilisez le Printemps de Démarrage il y a une méthode plus simple. Il suffit de définir la Jackson2ObjectMapperBuilder bean quelque part dans votre classe de Configuration:
et ajouter la coutume
HttpMessageConverter
à la liste desWebMvcConfigurerAdapter
message convertisseurs:and add the custom HttpMessageConverter to the list of WebMvcConfigurerAdapter message converters:
oui, par défaut SpringBoot ne prend pas en compte Jackson2ObjectMapperBuilder Bean. Si vous jetez un oeil sur la façon dont le défaut WebMvcConfigurerAdapter est initialisé, vous remarquerez qu'il utilise Jackson2ObjectMapperBuilder.json() méthode statique au lieu de Haricot injection
OriginalL'auteur WeMakeSoftware