Jackson ha superato le sottolineature a favore del caso dei cammelli


160

Recupero una stringa JSON da Internet; come la maggior parte di JSON che ho visto include tasti lunghi separati da caratteri di sottolineatura. In sostanza, il mio obiettivo è quello di deserializzare JSON in java-object, ma non uso i trattini bassi nel codice java.

Ad esempio, potrei avere una Userclasse con firstNamecampo nel caso del cammello, contemporaneamente ho bisogno in qualche modo di dire a Jackson di mappare la first_namechiave da JSON al firstNamecampo della classe. È possibile?

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

Risposte:


104

È necessario utilizzare il @JsonPropertycampo che si desidera modificare la mappatura dei nomi predefinita.

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

Per maggiori informazioni: l' API


86
Non farlo, altrimenti dovrai farlo per ogni proprietà. Vedi la risposta di thehpi sotto.
Ryan Shillington,

Sono stato in grado di annotare solo una proprietà, ma ha cambiato l'ordine delle proprietà nella stringa generata: le proprietà annotate sono state visualizzate per ultime. (Jackson 2.3.0)
eebbesen,

1
@RyanShillington - Correggimi se sbaglio, ma questa è la tua unica opzione se la stringa JSON da cui stai analizzando non usa un formato coerente, cioè usa sia camelCase che underscore?
David R

@DavidR È corretto. Suppongo che non sia possibile correggere i dati di origine? Che schifo
Ryan Shillington,

@PaulTsai ok, quindi sentiti libero di usarli :)
Alex

351

Puoi configurare il ObjectMapperper convertire la custodia del cammello in nomi con un trattino basso:

objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);

Oppure annota una classe di modello specifica con questa annotazione:

@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)

Prima di Jackson 2.7, la costante era chiamata:

PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES

5
Si noti che questo è stato introdotto solo in Jackson 1.9.
David Moles,

62
@deprecated Da 2.7 utilizzare invece SNAKE_CASE;
Thermech

1
one qq: quando utilizzo la strategia di denominazione snake_case i file json con caratteri di sottolineatura verranno deserializzati in caso di cammello?
Ram Patra,

2
@Ramswaroop Sì, questo fa parlare sia Jackson che aspettarsi snake_case
Drew Stephens,

1
@Ramswaroop Per me con Jackson 2.7.3 e le proprietà annotate con just @JsonProperty(nome dedotto dalle normali camelCaseproprietà Java) PropertyNamingStrategy.SNAKE_CASEhanno impedito alla deserializzazione di funzionare con camelCase JSON (come avevo usato) e richiedono snake_case.
Drew Stephens,

119

Se è un'applicazione di avvio a molla, nel file application.properties, basta usare

spring.jackson.property-naming-strategy = SNAKE_CASE

Oppure annota la classe del modello con questa annotazione.

@JsonNaming (PropertyNamingStrategy.SnakeCaseStrategy.class)


3
Se annoto la mia classe con "@JsonNaming (PropertyNamingStrategy.SnakeCaseStrategy.class)" funziona. Ma se uso "spring.jackson.property-naming-strategy = SNAKE_CASE" in "application.properties" non lo farà. Sto usando "Spring Boot (v2.0.0.BUILD-SNAPSHOT)". Hai qualche idea ?
Bruno,

1
lo stesso qui, spring.jackson.property-naming-strategy=SNAKE_CASEnon funziona, sto usando Spring Boot 2.0
soulmachine

1
stesso qui, spring.jackson.property-naming-strategy = SNAKE_CASE non funziona, sto usando Spring Boot 2.0.5. Ma usare l'annotazione funziona per me
Neo Pham,

Forse il tuo ObjectMappernon è stato creato da Spring? Crea una classe @Configuration con un metodo @Bean che restituisce un ObjectMapper. Non sono sicuro se questo è necessario.
Ondra Žižka,

48

Se lo desideri per una singola classe, puoi utilizzare PropertyNamingStrategy con @JsonNaming , in questo modo:

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

    String businessName;
    String businessLegalName;

}

Si serializzerà per:

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

Dal momento che Jackson 2.7l' LowerCaseWithUnderscoresStrategyin deprecato a favore di SnakeCaseStrategy, così si dovrebbe usare:

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

    String businessName;
    String businessLegalName;

}

29

Le risposte di cui sopra riguardanti @JsonPropertye CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORESsono accurate al 100%, anche se alcune persone (come me) potrebbero tentare di farlo all'interno di un'applicazione Spring MVC con configurazione basata su codice. Ecco un codice di esempio (che ho all'interno Beans.java) per ottenere l'effetto desiderato:

@Bean
public ObjectMapper jacksonObjectMapper() {
    return new ObjectMapper().setPropertyNamingStrategy(
            PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES);
}

9
Un'alternativa per Spring Boot, se si utilizza Spring Boot <= 1.3, in application.propertiesaggiunta spring.jackson.property-naming-strategy=CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCOR‌​ES. Per Spring Boot 1.4 utilizzare spring.jackson.property-naming-strategy=SNAKE_CASEinvece.
Dump Cake

1
@zapl sì, hai ragione, probabilmente ho menzionato la versione di Jackson al posto della versione a molla. Vorrei eliminare quel commento per evitare confusione.
Ram Patra,

1
A partire dalla versione 2.7 di Jackson è SNAKE_CASE. Questo ha funzionato per me: final ObjectMapper objectMapper = new ObjectMapper().setPropertyNamingStrategy( PropertyNamingStrategy.SNAKE_CASE);
Jonathan,

12

La best practice corrente è configurare Jackson all'interno del file application.yml(o properties).

Esempio:

spring:
  jackson:
    property-naming-strategy: SNAKE_CASE

Se hai requisiti di configurazione più complessi, puoi anche configurare Jackson a livello di codice.

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
    }

} 

Sai se hai un'altra istanza di jackson2objectmapper che viene caricata e ignorata? E puoi confermare che viene caricato anche questo bean?
Kenny Cason,

Dai anche un giro alla soluzione di DuffJ. È abbastanza simile.
Kenny Cason,

Penso che modificare le proprietà sia la strada giusta; e anche raccomandato. Questo fa lo stesso.
WesternGun

@WesternGun buona chiamata. Tendo a farlo tramite yaml / properties quando possibile.
Kenny Cason,

6

Ci sono alcune risposte qui che indicano entrambe le strategie per 2 diverse versioni della libreria Jackson qui sotto:

Per Jackson 2.6. *

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

Per Jackson 2.7. *

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

di nuovo hanno deprecato alcuni valori, ora hanno KEBAB_CASE, gnam!
Kalpesh Soni,

FTR: il caso kebab non è snake_case ;-)
René
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.