Cách chỉ định jackson chỉ sử dụng các trường - tốt nhất là trên toàn cầu


189

Hành vi jackon mặc định dường như sử dụng cả hai thuộc tính (getters và setters) và các trường để tuần tự hóa và giải tuần tự hóa thành json.

Tôi muốn sử dụng các trường làm nguồn chính của cấu hình tuần tự hóa và do đó không muốn jackson xem xét các thuộc tính.

Tôi có thể làm điều này trên cơ sở lớp học cá nhân với chú thích:

 @JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)

Nhưng tôi không muốn phải đưa thứ này lên từng lớp ...

Có thể cấu hình này trên toàn cầu? Giống như thêm một số vào Object Mapper?


1
Tim đã đưa ra một câu trả lời tốt. Một khả năng khác là nếu bạn có một lớp cơ sở chung, bạn có thể đặt các chú thích lớp cho lớp đó; chú thích được kế thừa bởi Jackson.
StaxMan

1
Tôi nghĩ rằng tôi đã thử điều đó, nhưng có vẻ như bạn phải nói với các lớp con sử dụng những gì trường hợp cơ sở định nghĩa ...
Michael Wiles

2
Không, trừ khi lớp con ghi đè chú thích lớp, chú thích của cha mẹ được hiển thị như thể chúng là một phần của định nghĩa lớp con (nếu không, đây sẽ là một lỗi). Đây không nhất thiết là cách JDK xử lý các chú thích, nhưng Jackson thực hiện kế thừa hoàn toàn cho các chú thích (ngay cả đối với các chú thích phương thức).
StaxMan

Coi chừng INFER_PROPERTY_MUTATORScờ. Nó buộc khả năng hiển thị của setters nếu có một getter hoặc trường nhìn thấy được.
Ondra Žižka

Câu trả lời:


157

Bạn có thể định cấu hình các ObjectMappers như thế này:

ObjectMapper mapper  = new ObjectMapper();
mapper.setVisibility(mapper.getSerializationConfig().getDefaultVisibilityChecker()
                .withFieldVisibility(JsonAutoDetect.Visibility.ANY)
                .withGetterVisibility(JsonAutoDetect.Visibility.NONE)
                .withSetterVisibility(JsonAutoDetect.Visibility.NONE)
                .withCreatorVisibility(JsonAutoDetect.Visibility.NONE));

Nếu bạn muốn nó được đặt trên toàn cầu, tôi thường truy cập một trình ánh xạ được cấu hình thông qua lớp trình bao bọc.


3
Tốt, mặc dù tôi nghĩ rằng bạn cũng có thể cần phải thiết lập các phương thức kiểm tra (withXxx () thường tạo một đối tượng mới). Vì vậy, một cái gì đó như 'mapper.setVisibilityChecker (mapper.getVisibilityChecker (). Với ...);'
StaxMan

@StaxMan gọi tốt trên setVisibilityChecker, tôi đã chỉnh sửa câu trả lời để phản ánh.
Kevin Bowersox

42
withGetterVisibilitykhông bao gồm is*các phương pháp, nhưng có withIsGetterVisibilitycho chúng.
qerub

13
setVisibilityCheckerbị phản đối Sử dụng setVisibilitythay thế.
0x7d7b

1
Đây chỉ là những gì tôi cần! Cấu hình này cho phép tôi sử dụng Mixin để dễ dàng chuyển đổi các thực thể Hibernate thành DTOs. Theo mặc định, ObjectMapper tuần tự hóa mọi thứ và Mixin sẽ phải chỉ định các thuộc tính nào cần bỏ qua (nghĩa là phép trừ thay vì giao điểm).
TastyWheat

150

Trong Jackson 2.0 trở lên, bạn chỉ cần sử dụng:

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;   

...

ObjectMapper mapper = new ObjectMapper();    
mapper.setVisibility(PropertyAccessor.ALL, Visibility.NONE);
mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);

để tắt tự động phát hiện.


1
Xin chào các bạn, tôi đang sử dụng bình Jackson 1.9.0. Tôi đang nhận được thuộc tính json bổ sung, trong khi tuần tự hóa đối tượng thành chuỗi json. Tôi cần lấy chuỗi json, chỉ chứa các biến được đề cập với @JsonProperty. Bạn có thể vui lòng giúp tôi về điều này?
jrhamza

7
Bạn có thể bắt đầu với chú thích lớp được đề cập trong câu hỏi OP: @JsonAutoDetect(fieldVisibility = Visibility.NONE, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)Tiếp theo, bạn phải chú thích từng thuộc tính bạn muốn đưa vào@JsonProperty
lukk

Cảm ơn! Trước đây, tôi đã tìm thấy nhiều ví dụ mã trong đó JsonMethod được tham chiếu thay vì PropertyAccessor. Nếu bạn tìm kiếm JsonMethod, bạn hiếm khi nhận được liên kết đến PropertyAccessor thì ... Cách tốt nhất để tìm tên lớp thay thế trong các tạo phẩm kế tiếp là gì? Có thể khó khăn và khó chịu, không?
philburns 26/03/19

38

Cụ thể cho boolean is*()getters:

Tôi đã dành rất nhiều thời gian cho lý do tại sao không dưới đây

  @JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)

cũng không phải cái này

  setVisibility(PropertyAccessor.SETTER, JsonAutoDetect.Visibility.NONE);
  setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.NONE);
  setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);

làm việc cho Boolean Getter / Setter của tôi.

Giải pháp rất đơn giản:

  @JsonAutoDetect(isGetterVisibility = Visibility.NONE, ...          
  setVisibility(PropertyAccessor.IS_GETTER, JsonAutoDetect.Visibility.NONE);

CẬP NHẬT: spring-boot cho phép cấu hình nó:

jackson:
  visibility.field: any
  visibility.getter: none
  visibility.setter: none
  visibility.is-getter: none

Xem các thuộc tính ứng dụng phổ biến # JACKSON


1
Bạn có thể giải thích cách áp dụng giải pháp đơn giản cho lớp đậu?
Pavel Niedoba 18/03/2016

1
Cảm ơn bạn. Đó là ngày tiết kiệm hơn cho tôi.
nắm bắt

Đây không phải là một câu trả lời cho câu hỏi và khá sai lệch.
Ondra Žižka

14

cho jackson 1.9.10 tôi sử dụng

ObjectMapper mapper = new ObjectMapper();

mapper.setVisibility(JsonMethod.ALL, Visibility.NONE);
mapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);

để biến tự động cống hiến.


2
Đó chính là cách giải quyết. Cảm ơn.
cuneytykaya

tự hỏi nếu có bất kỳ sự khác biệt giữa làm điều này và vô hiệu hóa "tự động phát hiện".
xenoterracide

10

Làm thế nào về điều này: Tôi đã sử dụng nó với một mixin

đối tượng không tuân thủ

@Entity
@Getter
@NoArgsConstructor
public class Telemetry {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long pk;
    private String id;
    private String organizationId;
    private String baseType;
    private String name;
    private Double lat;
    private Double lon;
    private Instant updateTimestamp;
}

Mixin:

@JsonAutoDetect(fieldVisibility = ANY, getterVisibility = NONE, setterVisibility = NONE)
public static class TelemetryMixin {}

Sử dụng:

    ObjectMapper om = objectMapper.addMixIn(Telemetry.class, TelemetryMixin.class);
    Telemetry[] telemetries = om.readValue(someJson, Telemetry[].class);

Không có gì nói rằng bạn không thể nghiên cứu bất kỳ số lượng các lớp và áp dụng cùng một mixin.

Nếu bạn không quen thuộc với mixin, thì chúng chỉ đơn giản là về mặt khái niệm: Cấu trúc của mixin được áp đặt siêu hạng cho lớp mục tiêu (theo jackson, không liên quan đến JVM).


3

Nếu bạn muốn có một cách để làm điều này trên toàn cầu mà không phải lo lắng về cấu hình của bạn ObjectMapper, bạn có thể tạo chú thích của riêng mình:

@Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonAutoDetect(
        getterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE,
        setterVisibility = JsonAutoDetect.Visibility.NONE, fieldVisibility = JsonAutoDetect.Visibility.NONE,
        creatorVisibility = JsonAutoDetect.Visibility.NONE
)
public @interface JsonExplicit {
}

Bây giờ bạn chỉ cần chú thích các lớp học của bạn @JsonExplicitvà bạn tốt để đi!

Ngoài ra, hãy đảm bảo chỉnh sửa cuộc gọi ở trên @JsonAutoDetectđể đảm bảo bạn có các giá trị được đặt thành những gì hoạt động với chương trình của bạn.

Tín dụng vào https://stackoverflow.com/a/13408807 để giúp tôi tìm hiểu về@JacksonAnnotationsInside


3

Nếu bạn sử dụng Spring Boot, bạn có thể định cấu hình Jackson trên toàn cầu như sau:

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

@Configuration
public class JacksonObjectMapperConfiguration implements Jackson2ObjectMapperBuilderCustomizer {

    @Override
    public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
        jacksonObjectMapperBuilder.visibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
        jacksonObjectMapperBuilder.visibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
        jacksonObjectMapperBuilder.visibility(PropertyAccessor.CREATOR, JsonAutoDetect.Visibility.ANY);
    }

}
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.