简体   繁体   English

如何从 spring 中的 JSON 响应中过滤属性?

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

I have a controller like the following,我有一个如下所示的 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);
    }

}

I have another controller like so,我有另一个 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);
    }

}

The structure of my result is as follows:我的结果结构如下:

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

This extends from the result class:这从结果 class 延伸而来:

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

    /*Constructors, getters and setters*/
}

Now the model that I am going to set into the results field is,现在我要设置到结果字段中的 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 */

}

Now for the TestController mentioned above, I would like to display all the fields in the json response, whereas in the SecondTestController I would like to mask (not show) the age attribute in the json response.现在对于上面提到的 TestController,我想显示 json 响应中的所有字段,而在 SecondTestController 中,我想屏蔽(不显示)json 响应中的 age 属性。 How can I achieve this in spring. Any help greatly appreciated!我怎样才能在 spring 中实现这一目标。非常感谢任何帮助!

Have you considered @JsonView ? 您是否考虑过@JsonView

It is supported by Spring MVC and allows you to filter fields depending on the context of serialization. Spring MVC支持它,它允许您根据序列化的上下文来过滤字段。

First define your views: 首先定义您的观点:

public class View {     

    interface SampleView { }  
    interface SampleViewWithAge extends SampleView { }   
}

Then annotate your fields using the desired view: 然后使用所需的视图注释字段:

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
 }

Finally annotate your handlers to use a view when serializing the response: 最后,在序列化响应时注释您的处理程序以使用视图:

@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() {
    ... 
}

I think the most simple way to do that is to use Jackson @JsonFilter if you want it dynamic. 我认为最简单的方法是使用Jackson @JsonFilter如果您希望它动态的话。

For instance, here could be an exemple with Spring Boot : 例如,这里可能是Spring Boot的一个例子:

Your document : 您的文件:

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

Modify your default configured HttpMessageConverter : 修改默认配置的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()));
            }
        }
    }
}

This Filter will serialize all by default. 默认情况下,此筛选器将全部序列化。 This step is mandatory, if you don't specify it, you will have an exception coming that he does not know myFilter when your controller will try to generate an object response. 此步骤是强制性的,如果不指定该步骤,则会出现一个异常,即将到来的时候他不知道myFilter ,此时您的控制器将尝试生成对象响应。

Then, in you controller, here is your regular endpoint that serialize all field (using the previously declared filter): 然后,在您的控制器中,这是您的常规端点,用于序列化所有字段(使用先前声明的过滤器):

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

And now, the endpoint to have the same object with only some fields serialized : 现在,端点具有相同的对象,并且只序列化了一些字段:

@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"

Override toString method in your modal class with required fields and convert it to json explicitly as below in your second controller method. 在模态类中使用必填字段覆盖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);

public class BeanFilterCustom { 公共类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();
}

} }

You can use @JsonIgnore on fields you don't want to be included in your JSON. 您可以在不想包含在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