1

I want to filter out some fields in the response. Filtering should be done before the Java object is serialised into the JSON. Consider:

public class Entity {

    @JsonProperty("some_property")
    String someProperty;

    @JsonProperty("nested_entity")
    @OneToMany(mappedBy = "entity", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    NestedEntity nestedEntity;

    // other fields for eg fieldA, fieldB
}

API endpoint

get api/entity/{id}?fields=some_property,field_a

Now the ask is, in the o/p we should filter out only someProperty and fieldA. Like

{
    "some_property": "foo",
    "field_a": "bar"
}

But since these are JSON fields not Java object fields I can't filter or get these fields them by Reflection. Is there a way we can achieve this, i.e. filtering of Java object based on json fields ?

FYI: The advantage of filtering before serialization is that the lazy-fields' DB calls are saved unless these fields are required

Thanks in advance!

1
  • 1
    See about @JsonFilter. You can apply filtering at serialization. Commented Oct 15, 2020 at 20:01

1 Answer 1

1

On the suggestion of @robocode using @JsonFilter and also to support empty fields or no fields filtering added JacksonConfiguration

@JsonFilter("entityFilter")
public class Entity {

    @JsonProperty("some_property")
    String someProperty;
    // other fields for eg fieldA, fieldB
}

@Configuration
public class JacksonConfiguration { 
    public JacksonConfiguration(ObjectMapper objectMapper) {
        objectMapper.setFilterProvider(new SimpleFilterProvider().setFailOnUnknownId(false));
    } 
}

public class FieldMapper {
    
    @SneakyThrows
    public static Dto getFilteredFields(Dto make, String fields[]) {
        ObjectMapper objectMapper = new ObjectMapper();
        if(ArrayUtils.isNotEmpty(fields)) {
            FilterProvider filters = new SimpleFilterProvider().addFilter(
                    "entityFilter", SimpleBeanPropertyFilter.filterOutAllExcept(fields)
            );
            objectMapper.setFilterProvider(filters);
        } else {
            objectMapper.setFilterProvider(new SimpleFilterProvider().setFailOnUnknownId(false));
        }
        JsonNode j = objectMapper.readTree(objectMapper.writeValueAsString(make));
        return objectMapper.convertValue(j, Dto.class);
    }
}

// controller code to get the dto for api/entity/{id}?fields=some_property,field_a
Dto filteredFields = getFilteredFields(dto, fields);
return filteredFields
Sign up to request clarification or add additional context in comments.

Comments

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.