Jackson surmontant les soulignés en faveur de Camel-Case

160

Je récupère une chaîne JSON sur Internet; comme la plupart des JSON que j'ai vu, il comprend de longues clés séparées par des traits de soulignement. Essentiellement, mon objectif est de désérialiser JSON en objets java, mais je n'utilise pas de traits de soulignement dans le code java.

Par exemple, je pourrais avoir une Userclasse avec un firstNamechamp dans camel-case, en même temps, j'ai besoin de dire à Jackson de mapper la first_nameclé de JSON au firstNamechamp de classe. C'est possible?

class User{
    protected String firstName;
    protected String getFirstName(){return firstName;}
}
user1384991
la source

Réponses:

104

Vous devez utiliser le @JsonPropertysur le champ pour lequel vous souhaitez modifier le mappage de nom par défaut.

class User{
    @JsonProperty("first_name")
    protected String firstName;
    protected String getFirstName(){return firstName;}
}

Pour plus d'informations: l' API

Alex
la source
86
Ne faites pas cela, sinon vous devrez le faire pour chaque propriété. Voir la réponse de thehpi ci-dessous.
Ryan Shillington du
Je n'ai pu annoter qu'une seule propriété, mais cela a changé l'ordre des propriétés dans la chaîne générée: les propriétés annotées sont apparues en dernier. (Jackson 2.3.0)
eebbesen
1
@RyanShillington - Corrigez-moi si je me trompe, mais c'est votre seule option si la chaîne JSON que vous analysez n'utilise pas un format cohérent, c'est-à-dire utilise à la fois camelCase et un trait de soulignement?
DavidR
@DavidR C'est correct. Je suppose que vous ne pouvez pas corriger les données source? Ça craint.
Ryan Shillington
@PaulTsai ok, alors n'hésitez pas à les utiliser :)
Alex
351

Vous pouvez configurer le ObjectMapperpour convertir la casse du chameau en noms avec un trait de soulignement:

objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);

Ou annotez une classe de modèle spécifique avec cette annotation:

@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)

Avant Jackson 2.7, la constante était nommée:

PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES
thehpi
la source
5
Notez que cela n'a été introduit que dans Jackson 1.9.
David Moles
62
@deprecated Depuis 2.7, utilisez plutôt SNAKE_CASE;
Thermech
1
one qq: quand j'utilise la stratégie de nommage snake_case, les fichiers json avec des traits de soulignement seront-ils désérialisés en cas de chameau?
Ram Patra
2
@Ramswaroop Oui, cela fait à la fois Jackson parler et s'attendre à snake_case
Drew Stephens
1
@Ramswaroop Pour moi, avec Jackson 2.7.3 et les propriétés annotées avec juste @JsonProperty(nom déduit des camelCasepropriétés Java normales ), la PropertyNamingStrategy.SNAKE_CASEdésérialisation a cessé de fonctionner avec camelCase JSON (comme je l'avais utilisé) et nécessite snake_case.
Drew Stephens le
119

Si c'est une application de démarrage à ressort, dans le fichier application.properties, utilisez simplement

spring.jackson.property-naming-strategy = SNAKE_CASE

Ou Annotez la classe de modèle avec cette annotation.

@JsonNaming (PropertyNamingStrategy.SnakeCaseStrategy.class)

adam.smithsonian01
la source
3
Si j'annote ma classe avec le "@JsonNaming (PropertyNamingStrategy.SnakeCaseStrategy.class)", cela fonctionne. Mais si j'utilise "spring.jackson.property-naming-strategy = SNAKE_CASE" dans "application.properties", ce ne sera pas le cas. J'utilise "Spring Boot (v2.0.0.BUILD-SNAPSHOT)". As tu des idées ?
Bruno
1
pareil ici, spring.jackson.property-naming-strategy=SNAKE_CASEne fonctionne pas, j'utilise Spring Boot 2.0
soulmachine
1
idem ici, spring.jackson.property-naming-strategy = SNAKE_CASE ne fonctionne pas, j'utilise Spring Boot 2.0.5. Mais utiliser l'annotation fonctionne pour moi
Neo Pham
Peut-être que votre ObjectMappern'est pas créé par Spring? Créez une classe @Configuration avec une méthode @Bean qui renvoie un ObjectMapper. Je ne sais pas si cela est nécessaire.
Ondra Žižka
48

Si vous le souhaitez pour une classe unique, vous pouvez utiliser PropertyNamingStrategy avec @JsonNaming , quelque chose comme ceci:

@JsonNaming(PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy.class)
public static class Request {

    String businessName;
    String businessLegalName;

}

Sera sérialisé pour:

{
    "business_name" : "",
    "business_legal_name" : ""
}

Depuis Jackson 2.7le LowerCaseWithUnderscoresStrategydéconseillé en faveur de SnakeCaseStrategy, vous devez donc utiliser:

@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
public static class Request {

    String businessName;
    String businessLegalName;

}
Arturo Volpe
la source
29

Les réponses ci-dessus concernant @JsonPropertyet CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORESsont précises à 100%, bien que certaines personnes (comme moi) puissent essayer de le faire dans une application Spring MVC avec une configuration basée sur le code. Voici un exemple de code (que j'ai à l'intérieur Beans.java) pour obtenir l'effet souhaité:

@Bean
public ObjectMapper jacksonObjectMapper() {
    return new ObjectMapper().setPropertyNamingStrategy(
            PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES);
}
Dawngerpony
la source
9
Une alternative à Spring Boot, si vous utilisez Spring Boot <= 1.3, dans application.propertiesadd spring.jackson.property-naming-strategy=CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCOR‌​ES. Pour Spring Boot 1.4, utilisez à la spring.jackson.property-naming-strategy=SNAKE_CASEplace.
Dump Cake
1
@zapl oui vous avez raison, j'ai probablement mentionné la version de jackson au lieu de la version de spring-boot. Permettez-moi de supprimer ce commentaire pour éviter toute confusion.
Ram Patra le
1
Depuis la version 2.7 de Jackson, il s'agit de SNAKE_CASE. Cela a fonctionné pour moi: final ObjectMapper objectMapper = new ObjectMapper().setPropertyNamingStrategy( PropertyNamingStrategy.SNAKE_CASE);
Jonathan
12

La meilleure pratique actuelle consiste à configurer Jackson dans le fichier application.yml(ou properties).

Exemple:

spring:
  jackson:
    property-naming-strategy: SNAKE_CASE

Si vous avez des exigences de configuration plus complexes, vous pouvez également configurer Jackson par programme.

import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

@Configuration
public class JacksonConfiguration {

    @Bean
    public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder() {
        return new Jackson2ObjectMapperBuilder()
                .propertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
        // insert other configurations
    }

} 
Kenny Cason
la source
Savez-vous si vous avez une autre instance de jackson2objectmapper en cours de chargement et en remplaçant celle-ci? Et pouvez-vous confirmer que même ce bean est chargé?
Kenny Cason
Donnez également un tourbillon à la solution de DuffJ. C'est assez similaire.
Kenny Cason
Je pense que modifier les propriétés est la bonne façon; et recommandé, aussi. Cela fait la même chose.
WesternGun
@WesternGun bon appel. J'ai tendance à le faire via yaml / properties lorsque cela est possible.
Kenny Cason
6

Il y a quelques réponses ici indiquant les deux stratégies pour 2 versions différentes de la bibliothèque Jackson ci-dessous:

Pour Jackson 2.6. *

ObjectMapper objMapper = new ObjectMapper(new JsonFactory()); // or YAMLFactory()
objMapper.setNamingStrategy(
     PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES);

Pour Jackson 2.7. *

ObjectMapper objMapper = new ObjectMapper(new JsonFactory()); // or YAMLFactory()
objMapper.setNamingStrategy(
     PropertyNamingStrategy.SNAKE_CASE);
Amit Kaneria
la source
encore une fois, ils ont déprécié certaines valeurs, maintenant ils ont KEBAB_CASE, miam!
Kalpesh Soni
FTR: kebab-case n'est pas snake_case ;-)
René