2

I have a jax-rs endpoint that should return a JSON object but i want to select some fields and hide some others, my code is like this :

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

My case here that i want to return a custom "Customer" for only selected fields.

I'm using jax-rs, jackson to unmarshall/marshall Object to JSON.

Any solution please.

Example of Customer class :

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

Output :

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

=> Result after select : fields =phoneNumber,customerId

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

I know when instantiate the object and do not set 'hide' properties and to include this annotation @JsonInclude(JsonInclude.Include.NON_NULL) would be a solution but it takes too much code and maintenance.

2
  • Show us the Jackson annotations you use on Customer. Commented Aug 2, 2018 at 12:24
  • Done @intentionallyleftblank, i've added the needed code Commented Aug 2, 2018 at 12:32

2 Answers 2

4

I think you should to add a component to that filter :

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


}

then to add that filter in your model :

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

Finally to use that filter:

String fields = "A,B,C,D";
CustomerFilterConfig.fieldNames.clear();
CustomerFilterConfig.fieldNames.addAll(Arrays.asList(fields.split(",")));
Sign up to request clarification or add additional context in comments.

Comments

1

There are several different ways to instruct jackson to not serialize properties. One of them is to annotate your ignore properties in the java class that is being serialized. In the example below, intValue would NOT be serialized in the json.

private String stringValue;

@JsonIgnore
private int intValue;

private boolean booleanValue;

Here is a good post that covers additional strategies for ignoring fields for json serialization.

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

3 Comments

I do confirm, but how can i doit dynamically! after instantiate the Object !
Are you saying your ignore fields are conditional at run time?
I have never used it, but did some searching and it looks like setting up @JsonFilter will give you what you want. You will have to read up on it to see how to fully implement it. It appears to give full control over what properties are serialized at run time.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.