Jackson pokonuje podkreślenia na korzyść obudowy wielbłąda


160

Pobieram ciąg JSON z Internetu; jak większość JSON, widziałem, że zawiera długie klucze, które są oddzielone podkreśleniami. Zasadniczo moim celem jest deserializacja JSON w obiekty java, ale nie używam podkreślenia w kodzie java.

Na przykład, mogę mieć Userklasę z firstNamepolem w przypadku wielbłąda, jednocześnie muszę jakoś powiedzieć Jacksonowi, aby zamapował first_nameklucz z JSON na firstNamepole klasy. Czy to możliwe?

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

Odpowiedzi:


103

Powinieneś użyć @JsonPropertypola, na którym chcesz zmienić domyślne mapowanie nazw.

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

Więcej informacji: API


86
Nie rób tego, bo inaczej będziesz musiał to zrobić dla każdej nieruchomości. Zobacz odpowiedź thehpi poniżej.
— Ryan Shillington,

Udało mi się dodać adnotację tylko do jednej właściwości, ale zmieniło to kolejność właściwości w wygenerowanym ciągu: właściwości z adnotacjami pojawiły się jako ostatnie. (Jackson
— 2.3.0

1
@RyanShillington - Popraw mnie, jeśli się mylę, ale to jedyna opcja, jeśli ciąg JSON, z którego analizujesz, nie używa spójnego formatu, tj. Używa zarówno camelCase, jak i podkreślenia?
— DavidR

@DavidR Zgadza się. Zakładam, że nie możesz naprawić danych źródłowych? To jest do bani.
— Ryan Shillington

@PaulTsai ok, więc nie krępuj się ich używać :)
— Alex

351

Możesz skonfigurować ObjectMapperkonwersję wielkości wielbłądów na nazwy z podkreśleniem:

objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);

Lub dodaj adnotację do określonej klasy modelu za pomocą tej adnotacji:

@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)

Przed Jacksonem 2.7 stała nosiła nazwę:

PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES

5
Zauważ, że zostało to wprowadzone tylko w Jackson 1.9.
— David Moles,

62
@deprecated Od wersji 2.7 zamiast tego użyj SNAKE_CASE;
— Thermech,

1
jeden qq: czy kiedy używam strategii nazewnictwa snake_case, pliki json z podkreśleniami będą deserializowane do obudowy wielbłąda?
— Ram Patra,

2
@Ramswaroop Tak, to sprawia, że ​​Jackson zarówno mówi, jak i oczekuje snake_case
— Drew Stephens

1
@Ramswaroop Dla mnie z Jacksonem 2.7.3 i właściwościami z adnotacją @JsonProperty(nazwa wywnioskowana z normalnych camelCasewłaściwości Javy) PropertyNamingStrategy.SNAKE_CASEspowodowała, że ​​deserializacja przestała działać z camelCase JSON (tak jak wcześniej) i wymagała snake_case.
— Drew Stephens

119

Jeśli jest to aplikacja uruchamiana wiosną, w pliku application.properties po prostu użyj

spring.jackson.property-naming-strategy = SNAKE_CASE

Lub Opisz klasę modelu tą adnotacją.

@JsonNaming (PropertyNamingStrategy.SnakeCaseStrategy.class)


3
Jeśli dodam do mojej klasy adnotację „@JsonNaming (PropertyNamingStrategy.SnakeCaseStrategy.class)”, to działa. Ale jeśli użyję „spring.jackson.property-naming-strategy = SNAKE_CASE” w „application.properties”, nie będzie. Używam „Spring Boot (v2.0.0.BUILD-SNAPSHOT)”. Czy masz jakies pomysły ?
— Bruno

1
to samo tutaj, spring.jackson.property-naming-strategy=SNAKE_CASEnie działa, używam Spring Boot 2.0
— soulmachine

1
to samo tutaj, spring.jackson.property-naming-strategy = SNAKE_CASE nie działa, używam Spring Boot 2.0.5. Ale używanie adnotacji działa dla mnie
— Neo Pham

Może Twój ObjectMappernie jest tworzony wiosną? Utwórz klasę @Configuration z metodą @Bean, która zwraca ObjectMapper. Nie jestem pewien, czy jest to konieczne.
— Ondra Žižka

48

Jeśli chcesz to dla pojedynczej klasy, możesz użyć PropertyNamingStrategy z @JsonNaming , coś takiego:

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

    String businessName;
    String businessLegalName;

}

Zostanie serializowany do:

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

Od w zastąpiona , dlatego należy używać:Jackson 2.7LowerCaseWithUnderscoresStrategySnakeCaseStrategy

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

    String businessName;
    String businessLegalName;

}

29

Powyższe odpowiedzi dotyczące @JsonPropertyi CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORESsą w 100% dokładne, chociaż niektórzy ludzie (tacy jak ja) mogą próbować to zrobić wewnątrz aplikacji Spring MVC z konfiguracją opartą na kodzie. Oto przykładowy kod (który mam w środku Beans.java), aby osiągnąć zamierzony efekt:

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

9
Alternatywa dla Spring Boot, jeśli używasz Spring Boot <= 1.3, w application.propertiesadd spring.jackson.property-naming-strategy=CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCOR‌​ES. W przypadku Spring Boot 1.4 użyj spring.jackson.property-naming-strategy=SNAKE_CASEzamiast tego.
— Dump Cake

1
@zapl tak, masz rację, prawdopodobnie wspomniałem o wersji Jacksona zamiast wersji spring-boot. Pozwolę sobie usunąć ten komentarz, aby uniknąć nieporozumień.
— Ram Patra

1
Od wersji 2.7 Jacksona jest to SNAKE_CASE. To zadziałało dla mnie: final ObjectMapper objectMapper = new ObjectMapper().setPropertyNamingStrategy( PropertyNamingStrategy.SNAKE_CASE);
— Jonathan

12

Obecnie najlepszą praktyką jest skonfigurowanie Jacksona w application.yml(lubproperties pliku ).

Przykład:

spring:
  jackson:
    property-naming-strategy: SNAKE_CASE

Jeśli masz bardziej złożone wymagania konfiguracyjne, możesz również skonfigurować Jacksona programowo.

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
    }

} 

Czy wiesz, czy masz inne wystąpienie ładowania jackson2objectmapper i nadpisywanie tego? Czy możesz potwierdzić, że nawet ta fasola jest ładowana?
— Kenny Cason

Daj także wir rozwiązaniu DuffJ. Jest całkiem podobnie.
— Kenny Cason,

Myślę, że poprawianie właściwości jest właściwą drogą; i również zalecane. Robi to samo co to.
— WesternGun

@WesternGun dobre połączenie. Jeśli to możliwe, robię to za pomocą yaml / properties.
— Kenny Cason,

6

Poniżej znajduje się kilka odpowiedzi wskazujących obie strategie dla 2 różnych wersji biblioteki Jacksona:

Dla Jacksona 2.6. *

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

Dla Jackson 2.7. *

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

ponownie wycofali niektóre wartości, teraz mają KEBAB_CASE, yum!
— Kalpesh Soni

FTR: kebab-case is not snake_case ;-)
— René
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.