Jackson khắc phục dấu gạch dưới ủng hộ trường hợp lạc đà


160

Tôi lấy một chuỗi JSON từ internet; giống như hầu hết các JSON tôi đã thấy nó bao gồm các khóa dài được phân tách bằng dấu gạch dưới. Về cơ bản, mục tiêu của tôi là giải tuần tự hóa JSON thành các đối tượng java, nhưng tôi không sử dụng dấu gạch dưới trong mã java.

Chẳng hạn, tôi có thể có một Userlớp với firstNametrường trong trường hợp lạc đà, đồng thời tôi cần bằng cách nào đó nói với Jackson để ánh xạ first_namekhóa từ JSON sang firstNametrường lớp. Có thể không?

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

Câu trả lời:


103

Bạn nên sử dụng @JsonPropertytrên trường bạn muốn thay đổi ánh xạ tên mặc định.

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

Để biết thêm thông tin: API


86
Đừng làm điều này, nếu không bạn sẽ phải làm điều đó cho mọi tài sản. Xem phản hồi của thehpi dưới đây.
Ryan Shillington

Tôi chỉ có thể chú thích một thuộc tính, nhưng nó đã thay đổi thứ tự các thuộc tính trong chuỗi được tạo: thuộc tính chú thích xuất hiện lần cuối. (Jackson 2.3.0)
eebbesen

1
@RyanShillington - Sửa lỗi cho tôi nếu tôi sai, nhưng đây là tùy chọn duy nhất của bạn nếu chuỗi JSON mà bạn đang phân tích cú pháp không sử dụng định dạng nhất quán, nghĩa là sử dụng cả camelCase và gạch dưới?
DavidR

@DavidR Đúng vậy. Tôi cho rằng bạn không thể sửa dữ liệu nguồn? Đó là hút.
Ryan Shillington

@PaulTsai ok, vì vậy hãy sử dụng chúng :)
Alex

351

Bạn có thể định cấu hình ObjectMapperđể chuyển đổi trường hợp lạc đà thành tên có dấu gạch dưới:

objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);

Hoặc chú thích một lớp mô hình cụ thể với chú thích này:

@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)

Trước Jackson 2.7, hằng số được đặt tên:

PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES

5
Lưu ý rằng điều này chỉ được giới thiệu trong Jackson 1.9.
David Moles

62
@deprecated Kể từ 2.7, hãy sử dụng SNAKE_CASE thay thế;
Thermech

1
một qq: khi tôi sử dụng chiến lược đặt tên của sn_case, các tệp json có dấu gạch dưới có được giải tuần tự hóa thành trường hợp lạc đà không?
Ram Patra

2
@Ramswaroop Vâng, điều này khiến Jackson vừa nói vừa mong chờ rắn_case
Drew Stephens

1
@Ramswaroop Đối với tôi với Jackson 2.7.3 và các thuộc tính được chú thích bằng chỉ @JsonProperty(tên được suy ra từ camelCasecác thuộc tính Java thông thường ) PropertyNamingStrategy.SNAKE_CASEđã khiến quá trình khử lưu huỳnh ngừng hoạt động với camelCase JSON (như tôi đã sử dụng) và yêu cầu sn_case.
Drew Stephens

119

Nếu là ứng dụng khởi động mùa xuân, trong tệp application.properIES, chỉ cần sử dụng

spring.jackson.property-naming-Strateg = SNAKE_CASE

Hoặc Chú thích lớp mô hình với chú thích này.

@JsonNaming (PropertyNamingStrargety.SnakeCaseStrargety. Class)


3
Nếu tôi chú thích lớp của tôi với "@JsonNaming (PropertyNamingStrargety.SnakeCaseStrargety. Class)" thì nó hoạt động. Nhưng nếu tôi sử dụng "spring.jackson.property-naming-Strateg = SNAKE_CASE" trong "application.properations" thì sẽ không được. Tôi đang sử dụng "Spring Boot (v2.0.0.BUILD-SNAPSHOT)". Bạn có bất cứ ý tưởng ?
Bruno

1
tương tự ở đây, spring.jackson.property-naming-strategy=SNAKE_CASEkhông hoạt động, tôi đang sử dụng Spring Boot 2.0
soulmachine

1
tương tự ở đây, spring.jackson.property-naming-Strateg = SNAKE_CASE không hoạt động, tôi đang sử dụng Spring Boot 2.0.5. Nhưng sử dụng chú thích đang làm việc cho tôi
Neo Phạm

Có lẽ bạn ObjectMapperkhông được tạo ra bởi mùa xuân? Tạo một lớp @Configuration bằng phương thức @Bean trả về ObjectMapper. Không chắc chắn nếu điều này là cần thiết.
Ondra ižka

48

Nếu bạn muốn điều này cho một Lớp duy nhất, bạn có thể sử dụng PropertyNamingStrargety với @JsonNaming , đại loại như thế này:

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

    String businessName;
    String businessLegalName;

}

Sẽ nối tiếp thành:

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

Kể từ khi Jackson 2.7các LowerCaseWithUnderscoresStrategytrong phản đối ủng hộ SnakeCaseStrategy, vì vậy bạn nên sử dụng:

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

    String businessName;
    String businessLegalName;

}

29

Các câu trả lời trên liên quan @JsonPropertyCAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORESchính xác 100%, mặc dù một số người (như tôi) có thể đang cố gắng thực hiện điều này bên trong ứng dụng Spring MVC với cấu hình dựa trên mã. Đây là mã mẫu (mà tôi có bên trong Beans.java) để đạt được hiệu quả mong muốn:

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

9
Một thay thế cho Spring Boot, nếu bạn đang sử dụng Spring Boot <= 1.3, application.propertiesthêm vào spring.jackson.property-naming-strategy=CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCOR‌​ES. spring.jackson.property-naming-strategy=SNAKE_CASEThay vào đó, sử dụng Spring Boot 1.4 .
Bánh Dump

1
@zapl vâng, bạn nói đúng, tôi có lẽ đã đề cập đến phiên bản của jackson thay vì phiên bản spring-boot. Hãy để tôi xóa bình luận đó để tránh nhầm lẫn.
Ram Patra

1
Kể từ phiên bản 2.7 của Jackson, nó là SNAKE_CASE. Điều này làm việc cho tôi: final ObjectMapper objectMapper = new ObjectMapper().setPropertyNamingStrategy( PropertyNamingStrategy.SNAKE_CASE);
Jonathan

12

Cách thực hành tốt nhất hiện nay là định cấu hình Jackson trong tệp application.yml(hoặc properties).

Thí dụ:

spring:
  jackson:
    property-naming-strategy: SNAKE_CASE

Nếu bạn có các yêu cầu cấu hình phức tạp hơn, bạn cũng có thể định cấu hình Jackson theo chương trình.

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
    }

} 

Bạn có biết nếu bạn có một phiên bản khác của jackson2objectmapper đang được tải và ghi đè lên cái này không? Và bạn có thể xác nhận rằng ngay cả đậu này đang được tải?
Kenny Cason

Cũng cho một giải pháp của DuffJ một cơn lốc. Nó khá giống nhau.
Kenny Cason

Tôi nghĩ rằng điều chỉnh các thuộc tính là đúng cách; và đề nghị, quá. Điều đó cũng giống như thế này.
WesternGun

@WesternGun gọi tốt. Tôi có xu hướng làm điều này thông qua yaml / property khi có thể.
Kenny Cason

6

Có vài câu trả lời ở đây chỉ ra cả hai chiến lược cho 2 phiên bản khác nhau của thư viện Jackson dưới đây:

Dành cho Jackson 2.6. *

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

Dành cho Jackson 2.7. *

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

một lần nữa họ không dùng nữa một số giá trị, bây giờ họ có KEBAB_CASE, yum!
Kalpesh Soni

FTR: kebab-case không phải là sn_case ;-)
René
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.