Динамическая c фильтрация поля в ответе от точки доступа RESTful webservice, которая возвращает список объектов домена - PullRequest
0 голосов
/ 31 марта 2020

Учитывая наличие веб-службы RESTful, разработанной с использованием среды Spring Boot, я хотел найти способ подавления birthDate всех пользователей в ответе. Это то, что я реализовал после поиска решения:

@RestController
public class UserResource {

    @Autowired
    private UserDAOservice userDAOService;

    @GetMapping("/users")
    public MappingJacksonValue users() {
        List<User> users = userDAOService.findAll();

        SimpleBeanPropertyFilter filter = SimpleBeanPropertyFilter
                .filterOutAllExcept("id", "name");

        FilterProvider filters = new SimpleFilterProvider().addFilter(
                "UserBirthDateFilter", filter);

        MappingJacksonValue mapping = new MappingJacksonValue(users);

        mapping.setFilters(filters);

        return mapping;
    }
}

Однако, когда я нажимаю на конечную точку покоя в браузере, я все еще вижу дату рождения пользователя в ответе:

{
    "id": 1,
    "name": "Adam",
    "birthDate": "1980-03-31T16:56:28.926+0000"
}

Вопрос 1: Какой API я могу использовать для достижения своей цели?

Далее, при условии, что я хочу придерживаться HATEOAS в комбинации с фильтрацией, как я могу go об этом. Я не могу выяснить API, которые можно использовать для совместного использования этих двух функций:

@GetMapping("/users/{id}")
public EntityModel<User> users(@PathVariable Integer id) {
    User user = userDAOService.findById(id);
    if (user == null) {
        throw new ResourceNotFoundException("id-" + id);
    }

    EntityModel<User> model = new EntityModel<>(user);
    WebMvcLinkBuilder linkTo = linkTo(methodOn(this.getClass()).users());
    model.add(linkTo.withRel("all-users"));

    //how do I combine EntityModel with filtering?
    return model;
}

Вопрос 2: Как мне объединить EntityModel с MappingJacksonValue?

Примечание: Мне известна аннотация @JsonIgnore, но при этом будет применяться фильтр для всех конечных точек, использующих домен; однако я хочу ограничить фильтрацию только двумя указанными выше конечными точками.

Ответы [ 3 ]

0 голосов
/ 31 марта 2020

Вы можете использовать функцию Джексона @JsonView. При этом вы можете указать определенное отображение запроса на создание сериализованного JSON с выбранным набором свойств.

public class View {
    interface UserDetails {}
}

public class User {

    @JsonView(View.UserDetails.class)
    private Long id;

    @JsonView(View.UserDetails.class)
    private String name;

    private String birthdate;
}

Контроллер будет похож на

    @JsonView(View.UserDetails.class)
    @GetMapping("/users")
    public MappingJacksonValue users() {
    ....
    }
0 голосов
/ 01 апреля 2020

Оказывается, чтобы это работало, я должен добавить аннотацию @JsonFilter над DTO и указать то же имя, которое использовалось при создании SimpleFilterProvider.

@JsonFilter("UserBirthDateFilter")
public class User {

    private Integer id;


    @Size(min=2, message="user name must be atleast 2 characters")
    @ApiModelProperty(notes="user name must be atleast 2 characters")
    private String name;

    @Past
    @ApiModelProperty(notes="birth date cannot be in the past")
    private Date birthDate;

   //other methods
}
0 голосов
/ 31 марта 2020

Существует более простой способ сделать это на своем объекте передачи (классе, который вы отправляете обратно клиенту), вы можете просто использовать аннотацию @JsonIgnore, чтобы убедиться, что поле не сериализовано, и, следовательно, отправлено в клиент. Поэтому просто добавьте @JsonIgnore в свой класс User для своего поля birthDay.

Вы также можете прочитать подробнее об этом подходе:

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

Если вам нужно вернуть другой объект для разных конечных точек (в вашем случае пользователь без рождения, только для указанных c), вам следует создать отдельные объекты переноса и использовать их для соответствующих конечных точек. Вы можете передать исходную сущность (Пользователь) в конструкторе этим классам и скопировать все необходимые поля.

...