簡體   English   中英

如何從 spring 中的 JSON 響應中過濾屬性?

[英]How to filter attributes from JSON response in spring?

我有一個如下所示的 controller,

@RequestMapping(value = "rest/v1/tester")
public class TestController {

    @RequestMapping(value = "/search", method = RequestMethod.GET)
    public ResponseEntity<SampleResults> search(@ModelAttribute("criteria")SampleCriteria criteria) throws Exception {
            SampleResults sampleResults = sampleService.search(criteria);
            return new ResponseEntity<>(sampleResults, OK);
    }

}

我有另一個 controller 像這樣,

@RequestMapping(value = "rest/v1/second")
public class SecondTestController {

@RequestMapping(value = "/search", method = RequestMethod.GET)
    public ResponseEntity<SampleResults> search(@ModelAttribute("criteria")SampleCriteria criteria) throws Exception {
            SampleResults sampleResults = secondsampleService.search(criteria);
            return new ResponseEntity<>(sampleResults, OK);
    }

}

我的結果結構如下:

public class SampleResults extends Results<SearchSummary, Sample> {
}

這從結果 class 延伸而來:

public class Results<SUMMARY,RESULTS> {
    private SUMMARY summary;
    private List<RESULTS> results;

    /*Constructors, getters and setters*/
}

現在我要設置到結果字段中的 model 是,

@JsonDeserialize(as = SampleImpl.class)
public interface Sample {

    Long getId();
    void setId(Long id);

    String getName();
    void setName(String name);

    int getAge();
    void setAge(int age);

}

public class SampleImpl implements Sample {

    private Long id;
    private String name;
    private int age;

    /* Getters and Setters */

}

現在對於上面提到的 TestController,我想顯示 json 響應中的所有字段,而在 SecondTestController 中,我想屏蔽(不顯示)json 響應中的 age 屬性。 我怎樣才能在 spring 中實現這一目標。非常感謝任何幫助!

您是否考慮過@JsonView

Spring MVC支持它,它允許您根據序列化的上下文來過濾字段。

首先定義您的觀點:

public class View {     

    interface SampleView { }  
    interface SampleViewWithAge extends SampleView { }   
}

然后使用所需的視圖注釋字段:

public class SampleImpl implements Sample { 

    @JsonView(View.SampleView.class)
    private Long id; 

    @JsonView(View.SampleView.class)
    private String name; 

    @JsonView(View.SampleViewWithAge.class)
    private int age;

    // Getters and setters
 }

最后,在序列化響應時注釋您的處理程序以使用視圖:

@JsonView(View.SampleView.class) 
@RequestMapping(value = "/search", method = RequestMethod.GET)  
public ResponseEntity<SampleResults> search() {
    ... 
}

@JsonView(View.SampleViewWithAge.class)
@RequestMapping(value = "/search", method = RequestMethod.GET)  
public ResponseEntity<SampleResults> searchWithAge() {
    ... 
}

我認為最簡單的方法是使用Jackson @JsonFilter如果您希望它動態的話。

例如,這里可能是Spring Boot的一個例子:

您的文件:

@JsonFilter("myFilter")
class Document {
   private field1;
   private field2;
}

修改默認配置的HttpMessageConverter:

@Configuration
class WebMvcConfiguration extends WebMvcConfigurationSupport {
    @Override
    protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        for(HttpMessageConverter<?> converter: converters) {
            if(converter instanceof MappingJackson2HttpMessageConverter) {
                ObjectMapper mapper = ((MappingJackson2HttpMessageConverter)converter).getObjectMapper();
                mapper.setFilterProvider(new SimpleFilterProvider().addFilter("myFilter", SimpleBeanPropertyFilter.serializeAll()));
            }
        }
    }
}

默認情況下,此篩選器將全部序列化。 此步驟是強制性的,如果不指定該步驟,則會出現一個異常,即將到來的時候他不知道myFilter ,此時您的控制器將嘗試生成對象響應。

然后,在您的控制器中,這是您的常規端點,用於序列化所有字段(使用先前聲明的過濾器):

@RequestMapping(value = "path/document", method = RequestMethod.GET)
public Document getDocumentWithAllFields() {
   return new Document("val1","val2");
} 
//result : {"field1":"val1","field2":"val2"}

現在,端點具有相同的對象,並且只序列化了一些字段:

@RequestMapping(value = "path/document", method = RequestMethod.GET)
public MappingJacksonValue getDocumentWithSomeFields(@RequestParam String[] fields) {
    MappingJacksonValue wrapper = new MappingJacksonValue(new Document("val1","val2"));
    FilterProvider filterProvider = new SimpleFilterProvider().addFilter("myFilter", 
         SimpleBeanPropertyFilter.filterOutAllExcept(fields)); 
    wrapper.setFilters(filterProvider);
    return wrapper;
} 
//result : {"field1":"val1"} (with 'fields' being a coma separated list, containing here just "field1"

在模態類中使用必填字段覆蓋toString方法,並將其顯式轉換為json,如下所示在第二個控制器方法中。

import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
//get yourObject

ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
String json = ow.writeValueAsString(yourObject);

公共類BeanFilterCustom {

public Object filterBean(Object object,String someBeanFilter)  {

    SimpleBeanPropertyFilter filter = SimpleBeanPropertyFilter.filterOutAllExcept("","");
    FilterProvider filters = new SimpleFilterProvider()
            .addFilter(someBeanFilter, filter);
    MappingJacksonValue mapping = new MappingJacksonValue(object);
    mapping.setFilters(filters);
    return mapping.getValue();
}

}

您可以在不想包含在JSON中的字段上使用@JsonIgnore

public class SampleImpl implements Sample {

    private Long id;
    private String name;

    @JsonIgnore
    private int age;

    /* Getters and Setters */

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM