แจ็คสันเอาชนะขีดล่างในกรณีอูฐ


160

ฉันดึงสตริง JSON จากอินเทอร์เน็ต เช่นเดียวกับ JSON ส่วนใหญ่ที่ฉันเคยเห็นมันมีปุ่มยาวที่คั่นด้วยเครื่องหมายขีดล่าง โดยพื้นฐานแล้วเป้าหมายของฉันคือการแยกแยะ JSON ให้เป็นจาวา - ออบเจ็กต์ แต่ฉันไม่ได้ใช้ขีดล่างในจาวา - โค้ด

ตัวอย่างเช่นฉันอาจมีUserคลาสที่มีfirstNameฟิลด์เป็นตัวอูฐในเวลาเดียวกันฉันต้องบอกแจ็คสันให้จับคู่first_nameคีย์จาก JSON กับfirstNameฟิลด์คลาส เป็นไปได้ไหม?

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

คำตอบ:


104

คุณควรใช้@JsonPropertyบนในฟิลด์ที่คุณต้องการเปลี่ยนการแมปชื่อเริ่มต้น

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

สำหรับข้อมูลเพิ่มเติม: API


86
อย่าทำสิ่งนี้ไม่เช่นนั้นคุณจะต้องทำเพื่อคุณสมบัติทุกอย่าง ดูการตอบสนองของ hpi ด้านล่าง
Ryan Shillington

ฉันสามารถเพิ่มคำอธิบายประกอบเดียวได้ แต่ก็เปลี่ยนลำดับของคุณสมบัติในสตริงที่สร้าง: คุณสมบัติคำอธิบายประกอบปรากฏขึ้นครั้งสุดท้าย (Jackson 2.3.0)
eebbesen

1
@RyanShillington - แก้ไขฉันถ้าฉันผิด แต่นี่เป็นตัวเลือกเดียวของคุณถ้าสตริง JSON ที่คุณแยกวิเคราะห์ไม่ได้ใช้รูปแบบที่สอดคล้องกันเช่นใช้ทั้ง camelCase และขีดล่าง?
DavidR

@DavidR นั่นถูกต้อง ฉันสมมติว่าคุณไม่สามารถแก้ไขข้อมูลต้นฉบับได้ ที่ดูด
Ryan Shillington

@PaulTsai ตกลงดังนั้นอย่าลังเลที่จะใช้พวกเขา :)
อเล็กซ์

351

คุณสามารถกำหนดค่าการObjectMapperแปลงกรณีตัวอูฐเป็นชื่อด้วยเครื่องหมายขีดล่าง:

objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);

หรือใส่คำอธิบายประกอบคลาสโมเดลเฉพาะด้วยหมายเหตุประกอบนี้:

@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)

ก่อนที่แจ็กสัน 2.7 ค่าคงที่ถูกตั้งชื่อ:

PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES

5
โปรดทราบว่านี่เป็นเพียงการแนะนำในแจ็คสัน 1.9
David Moles

62
@deprecated ตั้งแต่ 2.7 ใช้ SNAKE_CASE แทน
Thermech

1
หนึ่ง qq: เมื่อฉันใช้กลยุทธ์การตั้งชื่อ snake_case ไฟล์ json ที่มีการขีดเส้นใต้จะถูก deserialized ไปเป็นเคสอูฐหรือไม่?
Ram Patra

2
@Ramswaroop ใช่นี่ทำให้แจ็คสันพูดและคาดหวังว่า snake_case
Drew Stephens

1
@Ramswaroop สำหรับฉันด้วย Jackson 2.7.3 และคุณสมบัติที่มีหมายเหตุประกอบเพียง@JsonProperty(ชื่ออนุมานจากcamelCaseคุณสมบัติ Java ปกติ) PropertyNamingStrategy.SNAKE_CASEทำให้ deserialization หยุดทำงานกับ camelCase JSON (เหมือนที่ฉันใช้) และต้องการ snake_case
Drew Stephens

119

หากเป็นแอพพลิเคชั่นบู๊ทสปริงไฟล์ In application.properties ให้ใช้

spring.jackson.property ตั้งชื่อกลยุทธ์ = SNAKE_CASE

หรือใส่คำอธิบายประกอบโมเดลคลาสด้วยหมายเหตุประกอบนี้

@JsonNaming (PropertyNamingStrategy.SnakeCaseStrategy.class)


3
หากฉันใส่คำอธิบายประกอบคลาสของฉันด้วย "@JsonNaming (PropertyNamingStrategy.SnakeCaseStrategy.class)" ก็ใช้งานได้ แต่ถ้าฉันใช้ "spring.jackson.property-naming-strategy = SNAKE_CASE" ใน "application.properties" มันจะไม่เกิดขึ้น ฉันใช้ "Spring Boot (v2.0.0.BUILD-SNAPSHOT)" คุณมีความคิดใด ๆ
บรูโน่

1
เหมือนกันที่นี่spring.jackson.property-naming-strategy=SNAKE_CASEไม่ทำงานฉันใช้ Spring Boot 2.0
soulmachine

1
เหมือนกันที่นี่ spring.jackson.property-naming-strategy = SNAKE_CASE ไม่ทำงานฉันใช้ Spring Boot 2.0.5 แต่การใช้คำอธิบายประกอบนั้นใช้งานได้สำหรับฉัน
Neo Pham

บางทีคุณObjectMapperไม่ได้สร้างโดย Spring ใช่ไหม สร้างคลาส @Configuration ด้วยวิธีการ @Bean ที่ส่งคืน ObjectMapper ไม่แน่ใจว่าจำเป็นหรือไม่
Ondra Žižka

48

หากคุณต้องการสิ่งนี้สำหรับชั้นเดียวคุณสามารถใช้PropertyNamingStrategyกับ@JsonNaming ได้ดังนี้:

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

    String businessName;
    String businessLegalName;

}

จะทำให้เป็นอันดับ:

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

ตั้งแต่ในเลิกในความโปรดปรานของคุณจึงควรใช้:Jackson 2.7LowerCaseWithUnderscoresStrategySnakeCaseStrategy

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

    String businessName;
    String businessLegalName;

}

29

คำตอบข้างต้นเกี่ยวกับ@JsonPropertyและCAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORESถูกต้อง 100% แม้ว่าบางคน (เช่นฉัน) อาจพยายามทำสิ่งนี้ภายในแอปพลิเคชัน Spring MVC ที่มีการกำหนดค่ารหัสตาม นี่คือโค้ดตัวอย่าง (ที่ฉันมีอยู่Beans.java) เพื่อให้ได้เอฟเฟกต์ที่ต้องการ

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

9
ทางเลือกสำหรับฤดูใบไม้ผลิ Boot ถ้าคุณกำลังใช้ Spring Boot <= 1.3 ในการเพิ่มapplication.properties spring.jackson.property-naming-strategy=CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCOR‌​ESสำหรับ Spring Boot 1.4 ให้ใช้spring.jackson.property-naming-strategy=SNAKE_CASEแทน
เค้กการถ่ายโอนข้อมูล

1
@zapl ใช่คุณพูดถูกฉันอาจพูดถึงรุ่นของแจ็คสันแทนที่จะเป็นเวอร์ชั่นของสปริงบูต ให้ฉันลบความคิดเห็นนั้นเพื่อหลีกเลี่ยงความสับสน
Ram Patra

1
ในฐานะที่เป็นรุ่น 2.7 ของแจ็คสันมันเป็น SNAKE_CASE สิ่งนี้ใช้ได้กับฉัน: final ObjectMapper objectMapper = new ObjectMapper().setPropertyNamingStrategy( PropertyNamingStrategy.SNAKE_CASE);
Jonathan

12

แนวปฏิบัติที่เหมาะสมที่สุดในปัจจุบันคือการกำหนดค่า Jackson ภายในไฟล์application.yml(หรือproperties)

ตัวอย่าง:

spring:
  jackson:
    property-naming-strategy: SNAKE_CASE

หากคุณมีข้อกำหนดการกำหนดค่าที่ซับซ้อนมากขึ้นคุณสามารถกำหนดค่า Jackson โดยทางโปรแกรมได้

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
    }

} 

คุณรู้หรือไม่ถ้าคุณมีตัวอย่างของ jackson2objectmapper ที่กำลังโหลดและแทนที่อันนี้ และคุณสามารถยืนยันได้ว่าแม้ถั่วนี้กำลังโหลดอยู่
Kenny Cason

อีกทั้งให้การแก้ปัญหาของ DuffJ เป็นไปอย่างราบรื่น มันคล้ายกันมาก
Kenny Cason

ฉันคิดว่าการปรับเปลี่ยนคุณสมบัติเป็นวิธีที่ถูกต้อง; และแนะนำเช่นกัน นั่นทำเช่นเดียวกัน
WesternGun

@WesternGun โทรดี ฉันมักจะทำผ่าน yaml / คุณสมบัติเมื่อเป็นไปได้
Kenny Cason

6

มีคำตอบเล็กน้อยที่นี่ซึ่งแสดงถึงกลยุทธ์ทั้งสองสำหรับห้องสมุด Jackson รุ่นที่แตกต่างกันสองรุ่นด้านล่าง:

สำหรับแจ็คสัน 2.6. *

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

สำหรับแจ็คสัน 2.7. *

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

อีกครั้งพวกเขาเลิกใช้ค่าบางอย่างตอนนี้พวกเขามี KEBAB_CASE, yum!
Kalpesh Soni

FTR: kebab-case ไม่ใช่ snake_case ;-)
René
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.