2012-02-21 27 views
11

Có thể chọn lọc xác định khi chú thích @JsonFilter được sử dụng trong thời gian chạy không?@JsonFilter ném "JsonMappingException: Không thể giải quyết BeanPropertyFilter"

Tôi nhận được JsonMapping ngoại lệ ngoại lệ (xem bên dưới) khi tôi không cung cấp bộ lọc.

Bối cảnh:

tôi học được từ một recent StackOverflow post mà tôi có thể sử dụng @JsonFilter để tự động lọc các thuộc tính bean việc đăng. Điều này làm việc tuyệt vời. Sau khi thêm @JsonFilter("apiFilter") đến lớp tên miền của tôi và với việc bổ sung của mã này trong dịch vụ jax-rs tôi (bằng cách sử dụng thực hiện CXF), tôi có thể tự động lọc các thuộc tính trả về bởi API RESTful của tôi:

// shortened for brevity 
FilterProvider filters = new SimpleFilterProvider().addFilter("apiFilter", SimpleBeanPropertyFilter.filterOutAllExcept(filterProperties)); 

return mapper.filteredWriter(filters).writeValueAsString(user); 

Vấn đề có các cuộc gọi dịch vụ khác nhau mà tôi không muốn áp dụng bộ lọc. Trong những trường hợp đó, tôi muốn trả về toàn bộ lớp miền mà không lọc bất kỳ thuộc tính nào. Trong trường hợp tôi chỉ cố gắng để trở lại lớp miền tôi nhận được một ngoại lệ như sau:

Caused by: org.codehaus.jackson.map.JsonMappingException: Can not resolve BeanPropertyFilter with id 'apiFilter'; no FilterProvider configured 

at org.codehaus.jackson.map.ser.BeanSerializer.findFilter(BeanSerializer.java:252) 
at org.codehaus.jackson.map.ser.BeanSerializer.serializeFieldsFiltered(BeanSerializer.java:216) 
at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:140) 

Trả lời

6

Tôi nghĩ rằng bạn có thể đánh lừa các nhà văn lọc xác định một bộ lọc serialize trống cho trường hợp bạn muốn tất cả các thuộc tính seralized:

FilterProvider filters = new SimpleFilterProvider().addFilter("apiFilter", SimpleBeanPropertyFilter.serializeAllExcept(emptySet)); 

Bằng cách này, khi động cơ trông cho "apiFilter" bộ lọc được xác định tại @JsonFilter anotation, nó tìm thấy nó, nhưng nó sẽ không có bất kỳ tác dụng (như sẽ serialize tất cả các thuộc tính).

EDIT Ngoài ra, bạn có thể gọi phương thức nhà máy writer() thay vì filteredWriter():

ObjectWriter writer=null; 
if(aplyFilter) { 
    FilterProvider filters = new SimpleFilterProvider().addFilter("apiFilter", SimpleBeanPropertyFilter.filterOutAllExcept(filterProperties)); 
    writer=mapper.filteredWriter(filters); 
} else { 
    writer=mapper.writer(); 
} 

return writer.writeValueAsString(user); 

Tôi nghĩ rằng giải pháp cuối cùng này là cách sạch hơn, và thực sự tốt hơn.

+0

trong ví dụ đã chỉnh sửa của bạn, tôi có cần bao gồm mã để kiểm tra phương thức nhà văn nào cần gọi trong mọi cuộc gọi dịch vụ jax-rs không? trong một số phương thức dịch vụ, tôi trả về một đối tượng User thực tế thay vì một String. Rất cám ơn cho đầu vào của bạn! – Justin

+1

ok, tôi đã có cơ hội dùng thử. "lừa" bạn đề nghị làm việc nhưng tôi không thể nhận được đề xuất "sạch" thứ hai của bạn để làm việc. trong trường hợp đó tôi vẫn nhận được lỗi "no FilterProvider configure". cảm ơn một lần nữa. – Justin

+0

@Justin: tốt, IMO một cách giải quyết "không sạch" giải quyết một vấn đề là tốt hơn so với một "sạch" một không làm việc :). Hy vọng nó đã giúp giải quyết vấn đề của bạn. –

18

Tôi biết nó đã được trả lời nhưng đối với bất kỳ newcommers Jackson đã thực sự thêm khả năng không thất bại trên thiếu bộ lọc (JACKSON-650):
Bạn chỉ cần gọi SimpleFilterProvider.setFailOnUnknownId(false) và bạn sẽ không nhận được ngoại lệ này.

+0

cảm ơn bạn đã trả lời. Điều này là hữu ích – Justin

+4

Tất nhiên bạn vẫn cần phải cấu hình một SimpleFilterProvider ngay cả khi bạn sẽ không được sử dụng lọc ở tất cả với mapper bạn đang sử dụng. Ồ, tốt. – Jules

0

Tôi gặp sự cố tương tự khi nhận được cùng một Ngoại lệ, nhưng câu trả lời được chấp nhận không thực sự hữu ích trong trường hợp của tôi. Đây là giải pháp mà làm việc cho tôi:

Trong thiết lập của tôi, tôi đã sử dụng một tùy chỉnh JacksonSerializer như thế này:

@JsonSerialize(using = MyCustomSerializer.class) 
private Object someAttribute; 

Và serializer đã được thực hiện như thế này:

public class MyCustomSerializer extends JsonSerializer<Object> { 
    @Override 
    public void serialize(Object o, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { 
    if (o != null) { 
     jgen.writeObject(o); 
    } 
    } 
} 

Vấn đề với điều này là, miễn là bạn không sử dụng bất kỳ bộ lọc nào, nó hoạt động. Nó cũng hoạt động nếu bạn serialize nguyên thủy, vì vậy ví dụ nếu bạn sử dụng jgen.writeString(..). Nếu bạn sử dụng bộ lọc, mã đó sai, vì bộ lọc được lưu trữ ở đâu đó bên trong của SerializerProvider, không phải trong JsonGenerator. Nếu trong trường hợp đó bạn sử dụng máy phát điện trực tiếp, một SerializerProvider mới, mà không biết về các bộ lọc, được tạo ra trong nội bộ. Vì vậy, thay vì ngắn hơn jgen.writeObject(o) bạn cần gọi provider.defaultSerializeValue(o, jgen).Điều đó sẽ đảm bảo rằng các bộ lọc không bị mất và có thể được áp dụng.

Các vấn đề liên quan