Jackson überwindet Unterstriche zugunsten des Kamelfalls

160

Ich rufe eine JSON-Zeichenfolge aus dem Internet ab. Wie die meisten JSON, die ich gesehen habe, enthält es lange Schlüssel, die durch Unterstriche getrennt sind. Im Wesentlichen ist mein Ziel, JSON in Java-Objekte zu deserialisieren, aber ich verwende keine Unterstriche in Java-Code.

Zum Beispiel könnte ich eine UserKlasse mit firstNameFeld in Kamel-Fall haben, gleichzeitig muss ich Jackson irgendwie anweisen, den first_nameSchlüssel von JSON dem firstNameKlassenfeld zuzuordnen . Ist es möglich?

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

Antworten:

103

Sie sollten @JsonPropertydas Feld für das Feld verwenden, in dem Sie die Standardnamenzuordnung ändern möchten.

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

Für weitere Informationen: die API

Alex
quelle
86
Tun Sie dies nicht, sonst müssen Sie es für jede Immobilie tun. Siehe die Antwort von thehpi unten.
Ryan Shillington
Ich konnte nur eine Eigenschaft mit Anmerkungen versehen, aber die Reihenfolge der Eigenschaften in der generierten Zeichenfolge wurde geändert: Die mit Anmerkungen versehenen Eigenschaften wurden zuletzt angezeigt. (Jackson 2.3.0)
eebbesen
1
@RyanShillington - Korrigieren Sie mich, wenn ich falsch liege, aber dies ist Ihre einzige Option, wenn die JSON-Zeichenfolge, aus der Sie analysieren, kein konsistentes Format verwendet, dh sowohl camelCase als auch Unterstrich verwendet?
DavidR
@ DavidR Das ist richtig. Ich gehe davon aus, dass Sie die Quelldaten nicht reparieren können. Das ist Scheiße.
Ryan Shillington
@ Paulsai ok, also zögern Sie nicht, sie zu verwenden :)
Alex
351

Sie können das so konfigurieren ObjectMapper, dass Kamelkoffer in Namen mit einem Unterstrich umgewandelt werden:

objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);

Oder kommentieren Sie eine bestimmte Modellklasse mit dieser Anmerkung:

@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)

Vor Jackson 2.7 wurde die Konstante benannt:

PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES
thehpi
quelle
5
Beachten Sie, dass dies nur in Jackson 1.9 eingeführt wurde.
David Moles
62
@deprecated Seit 2.7 verwenden Sie stattdessen SNAKE_CASE.
Thermech
1
one qq: Wenn ich die Namensstrategie snake_case verwende, werden die JSON-Dateien mit Unterstrichen in Camel Case deserialisiert?
Ram Patra
2
@ Ramswaroop Ja, das lässt Jackson sprechen und erwarten snake_case
Drew Stephens
1
@Ramswaroop Für mich mit Jackson 2.7.3 und Eigenschaften, die mit just @JsonProperty(Name abgeleitet von normalen camelCaseJava-Eigenschaften) kommentiert wurden PropertyNamingStrategy.SNAKE_CASE, funktioniert die Deserialisierung nicht mehr mit camelCase JSON (wie ich es verwendet habe) und erfordert snake_case.
Drew Stephens
119

Wenn es sich um eine Spring-Boot-Anwendung handelt, verwenden Sie in der Datei application.properties einfach

spring.jackson.property-naming-Strategy = SNAKE_CASE

Oder Kommentieren Sie die Modellklasse mit dieser Anmerkung.

@JsonNaming (PropertyNamingStrategy.SnakeCaseStrategy.class)

adam.smithsonian01
quelle
3
Wenn ich meine Klasse mit "@JsonNaming (PropertyNamingStrategy.SnakeCaseStrategy.class)" kommentiere, funktioniert es. Aber wenn ich "spring.jackson.property-naming-Strategy = SNAKE_CASE" in "application.properties" verwende, wird es nicht. Ich verwende "Spring Boot (v2.0.0.BUILD-SNAPSHOT)". Hast du eine Idee ?
Bruno
1
das gleiche hier, spring.jackson.property-naming-strategy=SNAKE_CASEfunktioniert nicht, ich benutze Spring Boot 2.0
Soulmachine
1
Das gleiche gilt für spring.jackson.property-naming-Strategy = SNAKE_CASE. Ich verwende Spring Boot 2.0.5. Aber die Verwendung von Anmerkungen funktioniert für mich
Neo Pham
Vielleicht ist dein ObjectMappernicht vom Frühling erschaffen? Erstellen Sie eine @ Configuration-Klasse mit einer @ Bean-Methode, die einen ObjectMapper zurückgibt. Ich bin mir nicht sicher, ob dies notwendig ist.
Ondra Žižka
48

Wenn Sie dies für eine einzige Klasse wollen, können Sie das verwenden PropertyNamingStrategy mit dem @JsonNaming , etwa wie folgt:

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

    String businessName;
    String businessLegalName;

}

Wird serialisiert zu:

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

Da Jackson 2.7das LowerCaseWithUnderscoresStrategyin zugunsten von veraltet ist SnakeCaseStrategy, sollten Sie also verwenden:

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

    String businessName;
    String businessLegalName;

}
Arturo Volpe
quelle
29

Die obigen Antworten zu @JsonPropertyund CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORESsind 100% genau, obwohl einige Leute (wie ich) möglicherweise versuchen, dies in einer Spring MVC-Anwendung mit codebasierter Konfiguration zu tun. Hier ist ein Beispielcode (den ich im Inneren habe Beans.java), um den gewünschten Effekt zu erzielen:

@Bean
public ObjectMapper jacksonObjectMapper() {
    return new ObjectMapper().setPropertyNamingStrategy(
            PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES);
}
Dawngerpony
quelle
9
Eine Alternative für Spring Boot, wenn Sie Spring Boot <= 1.3 verwenden, application.propertieszusätzlich spring.jackson.property-naming-strategy=CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCOR‌​ES. Verwenden Sie spring.jackson.property-naming-strategy=SNAKE_CASEstattdessen für Spring Boot 1.4 .
Dump Cake
1
@zapl Ja, Sie haben Recht, ich habe wahrscheinlich Jacksons Version anstelle der Spring-Boot-Version erwähnt. Lassen Sie mich diesen Kommentar löschen, um Verwirrung zu vermeiden.
Ram Patra
1
Ab Version 2.7 von Jackson ist es SNAKE_CASE. Dies funktionierte für mich: final ObjectMapper objectMapper = new ObjectMapper().setPropertyNamingStrategy( PropertyNamingStrategy.SNAKE_CASE);
Jonathan
12

Die derzeit beste Vorgehensweise besteht darin, Jackson innerhalb von application.yml(oder) zu konfigurierenproperties ) Datei .

Beispiel:

spring:
  jackson:
    property-naming-strategy: SNAKE_CASE

Wenn Sie komplexere Konfigurationsanforderungen haben, können Sie Jackson auch programmgesteuert konfigurieren.

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
quelle
Wissen Sie, ob eine andere Instanz von jackson2objectmapper geladen wird und diese überschreibt? Und können Sie bestätigen, dass auch diese Bean geladen wird?
Kenny Cason
Geben Sie auch DuffJs Lösung einen Wirbel. Es ist ziemlich ähnlich.
Kenny Cason
Ich denke, die Eigenschaften zu optimieren ist der richtige Weg; und auch empfohlen. Das macht das Gleiche.
WesternGun
@ WesternGun guten Anruf. Ich neige dazu, dies über Yaml / Eigenschaften zu tun, wenn dies möglich ist.
Kenny Cason
6

Hier gibt es nur wenige Antworten, die beide Strategien für zwei verschiedene Versionen der Jackson-Bibliothek angeben:

Für Jackson 2.6. *

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

Für Jackson 2.7. *

ObjectMapper objMapper = new ObjectMapper(new JsonFactory()); // or YAMLFactory()
objMapper.setNamingStrategy(
     PropertyNamingStrategy.SNAKE_CASE);
Amit Kaneria
quelle
wieder haben sie einige Werte verworfen, jetzt haben sie KEBAB_CASE, yum!
Kalpesh Soni
FTR: Kebab-Fall ist nicht snake_case ;-)
René