【问题标题】:Hide some fields dynamically before marshalling (java to json)在编组之前动态隐藏一些字段(java到json)
【发布时间】:2018-08-02 12:16:39
【问题描述】:

我有一个 jax-rs 端点,它应该返回一个 JSON 对象,但我想选择一些字段并隐藏一些其他字段,我的代码是这样的:

import javax.ws.rs.BadRequestException;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;

import org.apache.commons.lang3.StringUtils;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;

@Component
@Path("/customers")
@Api(value = "Customers resource", produces = MediaType.APPLICATION_JSON_VALUE)
public class CustomersEndpoint{
    private final CustomersService customersService;

    public CustomersEndpoint(CustomersService customersService) {
        this.customersService = customersService;
    }
@GET
    @Path("{customerResourceId}")
    @Produces(MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "Get customer details")
    @ApiResponses(value = { @ApiResponse(code = 200, message = "Listing the customer details", response = **Customer**.class)") })
    public **Customer** getCustomerDetails(@ApiParam(value = "ID of customer to fetch") @PathParam("customerResourceId") String customerId,
                                      @QueryParam(value = "Retrieve only selected fields [by comma]") String fields )
            throws ApiException {       

        return this.customersService.getCustomerDetails(customerId,fields);
    }

我的情况是,我只想为选定的字段返回一个自定义的“Customer”。

我正在使用 jax-rs,jackson 将对象解组/编组为 JSON。

请提供任何解决方案。

客户类示例:

import java.util.ArrayList;
import java.util.List;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Customer {

        public Customer() {

            }

    public Customer(String customerId,String phoneNumber) {

        this.customerId=customerId;
        this.phoneNumber=phoneNumber;
    }

    /**
     * customer identifier
     */
    @JsonPropertyDescription("customer identifier")
    @JsonProperty("customerId")
    private String customerId;

    /**
     * customer phone number
     */
    @JsonPropertyDescription("customer phone number")
    @JsonProperty("phoneNumber")
    private String phoneNumber;
    /**
     * customer first number
     */
    @JsonPropertyDescription("customer first number")
    @JsonProperty("firstName")
    private String firstName;
    /**
     * customer last number
     */
    @JsonPropertyDescription("customer last number")
    @JsonProperty("lastName")
    private String lastName;
public String getCustomerId() {
        return customerId;
    }
    public Customer setCustomerId(String customerId) {
        this.customerId = customerId;
        return this;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }
    public Customer setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
        return this;
    }
    public String getFirstName() {
        return firstName;
    }
    public Customer setFirstName(String firstName) {
        this.firstName = firstName;
        return this;
    }
    public String getLastName() {
        return lastName;
    }
    public Customer setLastName(String lastName) {
        this.lastName = lastName;
        return this;
    }
}

输出:

{
  "customerId": "string",
  "phoneNumber": "string",
  "firstName": "string",
  "lastName": "string",
}

=> 选择后的结果:fields =phoneNumber,customerId

{
  "customerId": "string",
  "phoneNumber": "string"
}

我知道什么时候实例化对象并且不设置“隐藏”属性并包含此注释 @JsonInclude(JsonInclude.Include.NON_NULL) 将是一个解决方案,但它需要太多的代码和维护.

【问题讨论】:

  • 向我们展示您在 Customer 上使用的 Jackson 注释。
  • 完成@intentionallyleftblank,我已经添加了所需的代码

标签: java java-8 jackson jax-rs swagger


【解决方案1】:

我认为您应该向该过滤器添加一个组件:

@Component
public class CustomerFilterConfig {


    public static  Set<String> fieldNames = new HashSet<String>();

      @Bean
      public ObjectMapper objectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        SimpleFilterProvider simpleFilterProvider = new SimpleFilterProvider().setFailOnUnknownId(false);
        FilterProvider filters =simpleFilterProvider.setDefaultFilter(SimpleBeanPropertyFilter.filterOutAllExcept(fieldNames)).addFilter("customerFilter", SimpleBeanPropertyFilter.filterOutAllExcept(fieldNames));    
        objectMapper.setFilterProvider(filters);
        return objectMapper;
      } 


}

然后在您的模型中添加该过滤器:

@JsonFilter("customerFilter")
public class Customer {...}

最后使用那个过滤器:

String fields = "A,B,C,D";
CustomerFilterConfig.fieldNames.clear();
CustomerFilterConfig.fieldNames.addAll(Arrays.asList(fields.split(",")));

【讨论】:

    【解决方案2】:

    有几种不同的方法可以指示杰克逊不要序列化属性。其中之一是在正在序列化的 java 类中注释您的忽略属性。在下面的示例中,intValue 不会在 json 中序列化。

    private String stringValue;
    
    @JsonIgnore
    private int intValue;
    
    private boolean booleanValue;
    

    这是一篇很好的文章,涵盖了忽略 json 序列化字段的其他策略。

    http://www.baeldung.com/jackson-ignore-properties-on-serialization

    【讨论】:

    • 我确实确认了,但我怎么能动态地做到这一点!实例化对象后!
    • 您是说您的忽略字段在运行时是有条件的吗?
    • 我从未使用过它,但做了一些搜索,看起来设置 @JsonFilter 会给你想要的东西。您将不得不阅读它以了解如何完全实现它。它似乎可以完全控制在运行时序列化的属性。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-17
    • 2011-09-28
    • 2023-03-11
    • 2015-10-11
    相关资源
    最近更新 更多