当前位置: 首页 > 知识库问答 >
问题:

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

武嘉祥
2023-03-14

我有一个如下的控制器,

@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);
    }

}

我有另一个这样的控制器,

@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> {
}

这扩展了结果类:

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

    /*Constructors, getters and setters*/
}

现在,我将要设置到结果字段中的模型是,

@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我该如何实现这一点。非常感谢任何帮助!

共有3个答案

秦俊友
2023-03-14

使用必填字段重写模式类中的 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);
李甫
2023-03-14

您是否考虑过@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() {
    ... 
}
卢黎昕
2023-03-14

我认为最简单的方法是使用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的异常。

然后,在您的控制器中,这里是您序列化所有字段的常规endpoint(使用之前声明的过滤器):

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

现在,endpoint具有相同的对象,只有一些字段被序列化:

@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"
 类似资料:
  • 我使用的是Spring rest api 4. x。我们要求根据请求参数过滤响应中的字段。 我的用户对象: 在这种情况下,我只需要返回请求参数“字段”中的字段。JSON输出应该只包含名字和姓氏。 有几种方法可以根据对象过滤Jackson中的字段。在我的例子中,我需要通过将字段列表传递给Jackson序列化器来动态过滤。 请分享一些想法。

  • 我正在使用spring云网关作为边缘服务器。这就是流程 问题是,响应有响应是得到正确的200代码,注入的头是在响应上出现,但数据是不可用的响应。

  • 问题内容: 我花了很多时间为我的问题找到解决方案。 在此示例中,我在SetNavRecords数组中有2条记录。第一个是 “ Artikelnummer”:“ 21700” ,第二个是 “ Artikelnummer”:“ 21701” 每个记录都有一个数组“ OfflineVerkaufspreis”。 对我来说重要的是“ OfflineVerkaufspreis”中的“ Location_Co

  • 所以我有一个JSON url,里面有一些数据,比如名字、纬度和经度。然而,并不是每个对象都有经纬度,我只想显示具有经纬度的对象的名称。 带有lat和LNG的JSON示例对象:

  • 我需要在每个响应中添加标题。我正打算在下面做 我想在之后这样做,以便一旦控制器处理它,我只是在返回客户端之前添加标头。是正确的吗? 但如何编写响应过滤器? 在已返回,对响应执行任何操作都为时已晚。此时,整个响应已经发送到客户端,您的代码无法访问它。 我觉得上面的说法不对。我不能在过滤链之后添加标题。doFilter(请求、响应)?如果不是,为什么? 我使用的是spring mvc。

  • 问题内容: 有没有办法只处理过滤器中的响应。 下面编写的代码是否正确? 问题答案: 这取决于您想要什么。通常,您的样本虽然不正确。之后chain.doFilter又回来了,这是来不及做的任何回应。此时,整个响应已发送到客户端,您的代码无法访问它。 您需要做的是包装request和/或包装response到您自己的类中,将这些包装传递给doFilter方法,并处理包装中的所有处理。 为了使其更容易,