如何有条件地从 json 响应中排除 属性
How to conditionally exclude property from a json response
我有一个 class pojo 用于 return 对其余控制器中的 API 调用的响应
EmployeeResponse response = validationService.validate(request);
return new ResponseEntity<>(response, HttpStatus.OK);
但是现在我们想要对控制器 class 进行功能标记,以便在未设置配置 属性 时,响应将不包含 属性。我们该怎么做?
public class EmployeeResponse {
private String firstName;
private String lastName
private String address; // don't want to include this if boolean flag is not set
}
编辑:在此处添加控制器代码以显示一个对象是 returned 而没有被序列化,所以我不知道如何将 objectMapper 放入其中
@RestController
public class EmployeeController {
@PostMapping(value = "/validate", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<EmployeeResponse> get(final @RequestBody EmployeeRequest employeeRequest) {
MasterSubResponse response = validationService.validate(employeeRequest);
return new ResponseEntity<>(response, HttpStatus.OK);
}
}
您可以使用 Jackson Filter 来控制序列化过程。当使用 JSON 格式时,Spring Boot 将使用 ObjectMapper 实例来序列化响应和反序列化请求。这个想法是创建自定义过滤器,您将在其中放置业务逻辑,以便有条件地从 DTO 呈现所需的字段。然后你应该将该过滤器添加到对象映射器。
总而言之,以下是您需要遵循的步骤:
- 用
@JsonFilter("myFilter")
注释你的 DTO class
- 为您的自定义过滤器创建实现 class
- 为
ObjectMapper
创建配置 class,您将在其中设置在步骤 1 中创建的过滤器。
- 在
application.properties
文件中创建布尔标志
第 1 步:
import com.fasterxml.jackson.annotation.JsonFilter;
@JsonFilter("myFilter")
public class EmployeeResponse {
private String firstName;
private String lastName;
private String address;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
第 2 步:
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
import com.fasterxml.jackson.databind.ser.PropertyFilter;
import com.fasterxml.jackson.databind.ser.PropertyWriter;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
public class CustomFilter extends SimpleBeanPropertyFilter implements PropertyFilter {
private boolean isSerializable;
@Override
public void serializeAsField
(Object pojo, JsonGenerator jgen, SerializerProvider provider, PropertyWriter writer)
throws Exception {
if (include(writer)) {
if (!writer.getName().equals("address")) {
writer.serializeAsField(pojo, jgen, provider);
return;
}
System.out.println(isSerializable);
if (isSerializable) {
writer.serializeAsField(pojo, jgen, provider);
}
} else if (!jgen.canOmitFields()) { // since 2.3
writer.serializeAsOmittedField(pojo, jgen, provider);
}
}
@Override
protected boolean include(BeanPropertyWriter writer) {
return true;
}
@Override
protected boolean include(PropertyWriter writer) {
return true;
}
public boolean isSerializable() {
return isSerializable;
}
public void setSerializable(boolean serializable) {
isSerializable = serializable;
}
}
第 3 步:
import com.example.demo.filter.CustomFilter;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ObjectMapperCofiguration {
@Value("${isSerializable}")
public boolean isSerializable;
@Configuration
public class FilterConfiguration {
public FilterConfiguration(ObjectMapper objectMapper) {
SimpleFilterProvider simpleFilterProvider = new SimpleFilterProvider().setFailOnUnknownId(true);
CustomFilter customFilter = new CustomFilter();
customFilter.setSerializable(isSerializable);
simpleFilterProvider.addFilter("myFilter", customFilter);
objectMapper.setFilterProvider(simpleFilterProvider);
}
}
}
第 4 步:
在 application.properties 文件中添加以下内容 属性 :
isSerializable= false
第 5 步:
创建控制器 class 进行测试:
@RestController
public class RestSpringBootController {
@GetMapping(path = "/test")
public ResponseEntity<EmployeeResponse> test() throws JsonProcessingException {
EmployeeResponse employeeResponse = new EmployeeResponse();
employeeResponse.setAddress("addres");
employeeResponse.setFirstName("first");
employeeResponse.setLastName("last");
ResponseEntity<EmployeeResponse> responseEntity = ResponseEntity.ok(employeeResponse);
return responseEntity;
}
}
最后,当您启动 Spring 启动应用程序时,将布尔标志 isSerializable
设置为 false
您应该会得到以下响应:
如果您将 isSerializable
标志设置为 true
并重新启动应用程序,您应该看到以下响应:
我有一个 class pojo 用于 return 对其余控制器中的 API 调用的响应
EmployeeResponse response = validationService.validate(request);
return new ResponseEntity<>(response, HttpStatus.OK);
但是现在我们想要对控制器 class 进行功能标记,以便在未设置配置 属性 时,响应将不包含 属性。我们该怎么做?
public class EmployeeResponse {
private String firstName;
private String lastName
private String address; // don't want to include this if boolean flag is not set
}
编辑:在此处添加控制器代码以显示一个对象是 returned 而没有被序列化,所以我不知道如何将 objectMapper 放入其中
@RestController
public class EmployeeController {
@PostMapping(value = "/validate", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<EmployeeResponse> get(final @RequestBody EmployeeRequest employeeRequest) {
MasterSubResponse response = validationService.validate(employeeRequest);
return new ResponseEntity<>(response, HttpStatus.OK);
}
}
您可以使用 Jackson Filter 来控制序列化过程。当使用 JSON 格式时,Spring Boot 将使用 ObjectMapper 实例来序列化响应和反序列化请求。这个想法是创建自定义过滤器,您将在其中放置业务逻辑,以便有条件地从 DTO 呈现所需的字段。然后你应该将该过滤器添加到对象映射器。
总而言之,以下是您需要遵循的步骤:
- 用
@JsonFilter("myFilter")
注释你的 DTO class
- 为您的自定义过滤器创建实现 class
- 为
ObjectMapper
创建配置 class,您将在其中设置在步骤 1 中创建的过滤器。 - 在
application.properties
文件中创建布尔标志
第 1 步:
import com.fasterxml.jackson.annotation.JsonFilter;
@JsonFilter("myFilter")
public class EmployeeResponse {
private String firstName;
private String lastName;
private String address;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
第 2 步:
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
import com.fasterxml.jackson.databind.ser.PropertyFilter;
import com.fasterxml.jackson.databind.ser.PropertyWriter;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
public class CustomFilter extends SimpleBeanPropertyFilter implements PropertyFilter {
private boolean isSerializable;
@Override
public void serializeAsField
(Object pojo, JsonGenerator jgen, SerializerProvider provider, PropertyWriter writer)
throws Exception {
if (include(writer)) {
if (!writer.getName().equals("address")) {
writer.serializeAsField(pojo, jgen, provider);
return;
}
System.out.println(isSerializable);
if (isSerializable) {
writer.serializeAsField(pojo, jgen, provider);
}
} else if (!jgen.canOmitFields()) { // since 2.3
writer.serializeAsOmittedField(pojo, jgen, provider);
}
}
@Override
protected boolean include(BeanPropertyWriter writer) {
return true;
}
@Override
protected boolean include(PropertyWriter writer) {
return true;
}
public boolean isSerializable() {
return isSerializable;
}
public void setSerializable(boolean serializable) {
isSerializable = serializable;
}
}
第 3 步:
import com.example.demo.filter.CustomFilter;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ObjectMapperCofiguration {
@Value("${isSerializable}")
public boolean isSerializable;
@Configuration
public class FilterConfiguration {
public FilterConfiguration(ObjectMapper objectMapper) {
SimpleFilterProvider simpleFilterProvider = new SimpleFilterProvider().setFailOnUnknownId(true);
CustomFilter customFilter = new CustomFilter();
customFilter.setSerializable(isSerializable);
simpleFilterProvider.addFilter("myFilter", customFilter);
objectMapper.setFilterProvider(simpleFilterProvider);
}
}
}
第 4 步: 在 application.properties 文件中添加以下内容 属性 :
isSerializable= false
第 5 步:
创建控制器 class 进行测试:
@RestController
public class RestSpringBootController {
@GetMapping(path = "/test")
public ResponseEntity<EmployeeResponse> test() throws JsonProcessingException {
EmployeeResponse employeeResponse = new EmployeeResponse();
employeeResponse.setAddress("addres");
employeeResponse.setFirstName("first");
employeeResponse.setLastName("last");
ResponseEntity<EmployeeResponse> responseEntity = ResponseEntity.ok(employeeResponse);
return responseEntity;
}
}
最后,当您启动 Spring 启动应用程序时,将布尔标志 isSerializable
设置为 false
您应该会得到以下响应:
如果您将 isSerializable
标志设置为 true
并重新启动应用程序,您应该看到以下响应: