2012-12-07 28 views
19

Tôi cần loại trừ một số trường theo tên trước khi hiển thị. Danh sách các trường là động, vì vậy tôi không thể sử dụng chú thích.Làm cách nào để loại trừ các trường có Jackson không sử dụng chú thích?

Tôi đã cố gắng tạo bộ nối tiếp tùy chỉnh - nhưng tôi không thể lấy tên trường ở đó.

Trong Gson, tôi đã sử dụng Loại trừChiến lược, nhưng Jackson không có chức năng như vậy. Là nó?

+0

bạn có đang cố gắng loại trừ các thuộc tính trong thời gian chạy không? Ví dụ bạn có một bản đồ, và muốn loại trừ một số thuộc tính bên trong nó? – eugen

+0

có, nhưng phải là loại trừ dấu chấm như 'order.id' ' order.content.items' – Roman

Trả lời

24

Ví dụ dưới đây về loại trừ các trường theo tên là từ my blog post, Gson v Jackson - Part 4. (Tìm kiếm PropertyFilterMixIn.) Ví dụ này minh họa việc sử dụng một số FilterProvider với SimpleBeanPropertyFilter đến serializeAllExcept danh sách tên trường do người dùng chỉ định.

@JsonFilter("filter properties by name") 
class PropertyFilterMixIn {} 

class Bar 
{ 
    public String id = "42"; 
    public String name = "Fred"; 
    public String color = "blue"; 
    public Foo foo = new Foo(); 
} 

class Foo 
{ 
    public String id = "99"; 
    public String size = "big"; 
    public String height = "tall"; 
} 

public class JacksonFoo 
{ 
    public static void main(String[] args) throws Exception 
    { 
    ObjectMapper mapper = new ObjectMapper(); 
    mapper.getSerializationConfig().addMixInAnnotations( 
     Object.class, PropertyFilterMixIn.class); 

    String[] ignorableFieldNames = { "id", "color" }; 
    FilterProvider filters = new SimpleFilterProvider() 
     .addFilter("filter properties by name", 
      SimpleBeanPropertyFilter.serializeAllExcept( 
       ignorableFieldNames)); 
    ObjectWriter writer = mapper.writer(filters); 

    System.out.println(writer.writeValueAsString(new Bar())); 
    // output: 
    // {"name":"James","foo":{"size":"big","height":"tall"}} 
    } 
} 

(Lưu ý:. API liên quan có thể đã thay đổi một chút với một thông cáo Jackson gần đây)

Trong khi ví dụ không sử dụng một chú thích dường như không cần thiết, các chú thích không áp dụng cho các lĩnh vực được loại trừ. (Để giúp các API thay đổi để đơn giản hóa việc cấu hình cần thiết một chút, xin đừng ngần ngại bỏ phiếu cho việc thực hiện các vấn đề JACKSON-274

+1

Có, điều này hoạt động tốt. Cảm ơn bạn. Nhưng tôi vẫn không thể thực hiện các loại trừ phức tạp như 'something.items' (excluse items with root of something) – Roman

+4

Tôi tìm kiếm cùng một tính năng bạn cần, giải pháp đã cho nếu không đủ cho trường hợp của tôi, vì sử dụng những gì được đề xuất sẽ loại trừ các trường có cùng tên cũng nằm trong các đối tượng lồng nhau. Và tôi muốn loại trừ chúng chỉ ở cấp cao nhất. Vì vậy, nó là cần thiết một cách để xác định ở cấp độ tài sản đã được bỏ qua. –

+1

Vâng là giải pháp được tìm thấy bây giờ? – StackHola

6

Jackson dựa vào chú thích cho hầu hết mọi thứ như thế này;. Nhưng bạn không cần phải trực tiếp chú thích giá trị các lớp học. bạn cũng có thể sử dụng "trộn trong chú thích" (xem http://www.cowtowncoder.com/blog/archives/2009/08/entry_305.html).

Và sau đó có một vài lựa chọn, bạn có thể sử dụng ngoài cơ bản @JsonIgnore (mỗi tài sản) hoặc @JsonIgnoreProperties (mỗi lớp), xem http://www.cowtowncoder.com/blog/archives/2011/02/entry_443.html

+1

Tôi đang nói về loại trừ thời gian chạy. Tôi đã yêu cầu param những lĩnh vực để loại trừ và phải loại trừ nó từ phản ứng – Roman

+1

Sau đó đặt cược tốt nhất của bạn là xây dựng nó cho mình bằng cách sử dụng mô hình cây; hoặc triển khai "Bộ lọc JSON" (từ bài viết thứ hai). May mắn thay @ {Programmer Bruce} đã cho thấy làm thế nào để dlatter. – StaxMan

+0

@JsonIgnore cũng có thể được áp dụng cho phương thức getter. –

5

Nếu bạn có bộ lọc được xác định trên hai hoặc nhiều pojo, bạn có thể thử điều này:

@JsonFilter("filterAClass") 
class AClass 
{  
    public String id = "42"; 
    public String name = "Fred"; 
    public String color = "blue"; 
    public int sal = 56; 
    public BClass bclass = new BClass(); 
} 

//@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) 
@JsonFilter("filterBClass") 
class BClass 
{ 

    public String id = "99"; 
    public String size = "90"; 
    public String height = "tall"; 
    public String nulcheck =null; 
} 
public class MultipleFilterConcept { 
    public static void main(String[] args) throws Exception 
     { 
     ObjectMapper mapper = new ObjectMapper(); 
    // Exclude Null Fields 
     mapper.setSerializationInclusion(Inclusion.NON_NULL); 
     String[] ignorableFieldNames = { "id", "color" }; 
     String[] ignorableFieldNames1 = { "height","size" }; 
     FilterProvider filters = new SimpleFilterProvider() 
      .addFilter("filterAClass",SimpleBeanPropertyFilter.serializeAllExcept(ignorableFieldNames)) 
      .addFilter("filterBClass", SimpleBeanPropertyFilter.serializeAllExcept(ignorableFieldNames1)); 
     ObjectWriter writer = mapper.writer(filters); 
     System.out.println(writer.writeValueAsString(new AClass())); 

     } 
} 
9

Tôi đã viết thư viện để xử lý trường hợp sử dụng tương tự. Tôi cần phải lập trình bỏ qua các trường dựa trên người dùng yêu cầu dữ liệu. Các lựa chọn bình thường của Jackson chỉ là quá nặng tay, và tôi ghét cái cách nó làm cho mã của tôi trông như thế.

Thư viện giúp việc này dễ hiểu hơn rất nhiều. Nó cho phép bạn chỉ cần làm điều này:

import com.fasterxml.jackson.databind.ObjectMapper; 
import com.fasterxml.jackson.databind.module.SimpleModule; 
import com.monitorjbl.json.JsonView; 
import com.monitorjbl.json.JsonViewSerializer; 
import static com.monitorjbl.json.Match.match; 

//initialize jackson 
ObjectMapper mapper = new ObjectMapper(); 
SimpleModule module = new SimpleModule(); 
module.addSerializer(JsonView.class, new JsonViewSerializer()); 
mapper.registerModule(module); 

//get a list of the objects 
List<MyObject> list = myObjectService.list(); 

String json; 
if(user.getRole().equals('ADMIN')){ 
    json = mapper.writeValueAsString(list); 
} else { 
    json = mapper.writeValueAsString(JsonView.with(list) 
     .onClass(MyObject.class, match() 
      .exclude("*") 
      .include("name"))); 
} 

System.out.println(json); 

Mã có sẵn on GitHub, hy vọng nó sẽ giúp!

2

Tôi đã viết một thư viện có tên là Squiggly Filter, chọn trường dựa trên một tập con của cú pháp API biểu đồ Facebook. Ví dụ, để chọn mã vùng của trường địa chỉ của đối tượng người dùng, bạn sẽ sử dụng chuỗi truy vấn ?fields=address{zipCode}. Một trong những ưu điểm của Squiggly Filter là miễn là bạn có quyền truy cập vào ObjectMapper để render json, bạn không phải sửa đổi mã của bất kỳ phương thức điều khiển nào của mình.

Giả sử, bạn đang sử dụng API servlet, bạn có thể làm như sau:

1) Đăng ký một bộ lọc

<filter> 
    <filter-name>squigglyFilter</filter-name> 
    <filter-class>com.github.bohnman.squiggly.web.SquigglyRequestFilter</filter-class> 
</filter> 
<filter-mapping> 
    <filter-name>squigglyFilter</filter-name> 
    <url-pattern>/**</url-pattern> 
</filter-mapping> 

2) Khởi tạo ObjectMapper

Squiggly.init(objectMapper, new RequestSquigglyContextProvider()); 

3) Bạn hiện có thể lọc json của bạn

curl https://yourhost/path/to/endpoint?fields=field1,field2{nested1,nested2} 

Thông tin thêm về Bộ lọc Squiggly có sẵn trên github.

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