Jackson mengatasi garis bawah yang mendukung kasus unta

160

Saya mengambil string JSON dari internet; seperti kebanyakan JSON yang pernah saya lihat mencakup kunci-kunci panjang yang dipisahkan oleh garis bawah. Pada dasarnya, tujuan saya adalah deserialize JSON menjadi objek java, tapi saya tidak menggunakan garis bawah dalam kode java.

Sebagai contoh, saya mungkin memiliki Userkelas dengan firstNamebidang dalam camel-case, secara bersamaan saya perlu memberitahu Jackson untuk memetakan first_namekunci dari JSON ke firstNamebidang kelas. Apa itu mungkin?

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

Jawaban:

104

Anda harus menggunakan @JsonPropertybidang yang ingin Anda ubah pemetaan nama default.

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

Untuk info lebih lanjut: API

Alex
sumber
86
Jangan lakukan ini, atau Anda harus melakukannya untuk setiap properti. Lihat respons thehpi di bawah ini.
Ryan Shillington
Saya hanya dapat membubuhi keterangan satu properti, tetapi itu mengubah urutan properti dalam string yang dihasilkan: properti beranotasi muncul terakhir. (Jackson 2.3.0)
eebbesen
1
@RyanShillington - Perbaiki saya jika saya salah, tapi ini satu-satunya pilihan Anda jika string JSON yang Anda parsing tidak menggunakan format yang konsisten, yaitu menggunakan camelCase dan garis bawah?
DavidR
@ DavidR Itu benar. Saya berasumsi Anda tidak dapat memperbaiki data sumber? Itu menyebalkan.
Ryan Shillington
@ PaulTsai ok, jadi silakan menggunakannya :)
Alex
351

Anda dapat mengonfigurasi ObjectMapperuntuk mengonversi wadah unta ke nama dengan garis bawah:

objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);

Atau anotasi kelas model tertentu dengan anotasi ini:

@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)

Sebelum Jackson 2.7, konstanta diberi nama:

PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES
thehpi
sumber
5
Perhatikan bahwa ini hanya diperkenalkan di Jackson 1.9.
David Moles
62
@deprecated Sejak 2.7, gunakan SNAKE_CASE sebagai gantinya;
Thermech
1
satu qq: ketika saya menggunakan snake_case penamaan strategi, apakah file json dengan garis bawah akan di-deserialized ke case unta?
Ram Patra
2
@Ramswaroop Ya, ini membuat Jackson berbicara dan mengharapkan snake_case
Drew Stephens
1
@Ramswaroop Bagi saya dengan Jackson 2.7.3 dan properti beranotasi dengan just @JsonProperty(nama disimpulkan dari camelCaseproperti Java normal ) PropertyNamingStrategy.SNAKE_CASEmembuat deserialisasi berhenti bekerja dengan camelCase JSON (seperti yang saya gunakan) dan memerlukan snake_case.
Drew Stephens
119

Jika ini adalah aplikasi boot semi, Dalam file application.properties, cukup gunakan

spring.jackson.property-penamaan-strategi = SNAKE_CASE

Atau Anotasi kelas model dengan anotasi ini.

@JsonNaming (PropertyNamingStrategy.SnakeCaseStrategy.class)

adam.smithsonian01
sumber
3
Jika saya membubuhi keterangan kelas saya dengan "@JsonNaming (PropertyNamingStrategy.SnakeCaseStrategy.class)" itu berfungsi. Tetapi jika saya menggunakan "spring.jackson.property-penamaan-strategi = SNAKE_CASE" di "application.properties" tidak akan. Saya menggunakan "Spring Boot (v2.0.0.BUILD-SNAPSHOT)". Apakah Anda punya ide?
Bruno
1
sama di sini, spring.jackson.property-naming-strategy=SNAKE_CASEtidak berfungsi, saya menggunakan Spring Boot 2.0
soulmachine
1
sama di sini, spring.jackson.property-naming-strategy = SNAKE_CASE tidak berfungsi, saya menggunakan Spring Boot 2.0.5. Tetapi menggunakan anotasi bekerja untuk saya
Neo Pham
Mungkin Anda ObjectMappertidak dibuat oleh Spring? Buat kelas @Configuration dengan metode @Bean yang mengembalikan ObjectMapper. Tidak yakin apakah ini perlu.
Ondra Žižka
48

Jika Anda menginginkan ini untuk Kelas Tunggal, Anda dapat menggunakan PropertyNamingStrategy dengan @JsonNaming , sesuatu seperti ini:

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

    String businessName;
    String businessLegalName;

}

Akan bersambung ke:

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

Sejak Jackson 2.7itu LowerCaseWithUnderscoresStrategydi usang dalam mendukung SnakeCaseStrategy, sehingga Anda harus menggunakan:

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

    String businessName;
    String businessLegalName;

}
Arturo Volpe
sumber
29

Jawaban di atas mengenai @JsonPropertydan CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES100% akurat, meskipun beberapa orang (seperti saya) mungkin mencoba melakukan ini di dalam aplikasi Spring MVC dengan konfigurasi berbasis kode. Berikut kode contoh (yang saya miliki di dalam Beans.java) untuk mencapai efek yang diinginkan:

@Bean
public ObjectMapper jacksonObjectMapper() {
    return new ObjectMapper().setPropertyNamingStrategy(
            PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES);
}
Dawngerpony
sumber
9
Alternatif untuk Spring Boot, jika Anda menggunakan Spring Boot <= 1.3, di application.propertiestambahkan spring.jackson.property-naming-strategy=CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCOR‌​ES. Untuk Spring Boot 1.4 gunakan spring.jackson.property-naming-strategy=SNAKE_CASEsaja.
Kue Dump
1
@ zapl ya Anda benar, saya mungkin menyebutkan versi jackson bukan versi semi-boot. Biarkan saya menghapus komentar itu untuk menghindari kebingungan.
Ram Patra
1
Pada versi 2.7 dari Jackson itu adalah SNAKE_CASE. Ini bekerja untuk saya: final ObjectMapper objectMapper = new ObjectMapper().setPropertyNamingStrategy( PropertyNamingStrategy.SNAKE_CASE);
Jonathan
12

Praktik terbaik saat ini adalah mengonfigurasi Jackson di dalam application.yml(atauproperties ).

Contoh:

spring:
  jackson:
    property-naming-strategy: SNAKE_CASE

Jika Anda memiliki persyaratan konfigurasi yang lebih kompleks, Anda juga dapat mengonfigurasi Jackson secara terprogram.

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
sumber
Apakah Anda tahu jika Anda memiliki instance lain dari jackson2objectmapper yang sedang dimuat dan mengganti yang ini? Dan dapatkah Anda mengonfirmasi bahwa bahkan kacang ini sedang dimuat?
Kenny Cason
Juga berikan solusi DuffJ. Ini sangat mirip.
Kenny Cason
Saya pikir mengutak-atik properti adalah cara yang benar; dan direkomendasikan juga. Itu melakukan hal yang sama seperti ini.
WesternGun
@WesternGun panggilan bagus. Saya cenderung melakukan ini melalui yaml / properti bila memungkinkan.
Kenny Cason
6

Ada beberapa jawaban di sini yang menunjukkan kedua strategi untuk 2 versi berbeda dari perpustakaan Jackson di bawah ini:

Untuk Jackson 2.6. *

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

Untuk Jackson 2.7. *

ObjectMapper objMapper = new ObjectMapper(new JsonFactory()); // or YAMLFactory()
objMapper.setNamingStrategy(
     PropertyNamingStrategy.SNAKE_CASE);
Amit Kaneria
sumber
sekali lagi mereka mencabut beberapa nilai, sekarang mereka memiliki KEBAB_CASE, yum!
Kalpesh Soni
FTR: kebab-case bukan snake_case ;-)
René