Фильтровать ответ REST на основе одного из полей этого ответа - PullRequest
0 голосов
/ 08 ноября 2019

Итак, давайте представим, что у нас есть компания, которая продает страховые полисы. Многие агенты могут видеть одну политику, но каждый агент имеет свою собственную роль в каждой политике, поэтому он должен видеть только ограниченные данные.

@FilterableResource(fieldWithRole = "role") //my annotation @JsonFilter("filterable") inside
public class Policy {

    private String number;
    @FilterByRole(role = "MAIN_AGENT") //only for main
    private String cost;
    @FilterByRole(role = "MAIN_AGENT") //only for main
    private Person insurer;
    private Person insured;
    @JsonIgnore
    private String role; // for no one

}

public class Person {
    private String name;
    @FilterByRole(role = "MAIN_AGENT")
    private String mobile; //only for main
}

эти политики возвращаются из простого результата конечной точки отдыха / API / политик для результатаагент X:

[ 
{
    "number": "123",
    "cost": 123000,
    "insurer": [{"name": "John", "mobile": "443456434"}],
    "insured": [{"name": "Jey", "mobile": "13124124234"}],
    "role": "MAIN_AGENT"
},
{
    "number": "321",
    "cost": 321000,
    "insurer": [{"name": "Betty", "mobile": "14212442"}],
    "insured": [{"name": "Frank", "mobile": "32523523"}],
    "role": "AGENT"
}
]

результат должен быть отфильтрован в соответствии с моими аннотациями к:

[ 
{
    "number": "123",
    "cost": 123000,
    "insurer": [{"name": "John", "mobile": "443456434"}],
    "insured": [{"name": "Jey", "mobile": "13124124234"}],
},
{
    "number": "321",
    "insured": [{"name": "Frank"}],
}
]

, поэтому я решил, что могу отфильтровать их непосредственно перед отправкой обратно, используя фильтр Джексона (вот почемуЯ использовал JsonFilter). Вдохновение было @JsonView (Role.class), но проблема в том, что каждое поле не основано на контексте аутентификации (которое никогда не меняется), а в моем случае основано на каждом объекте политики, поэтому я ввел дополнительный FilterableResource, который даст мнезначение для каждой политики.

Мой фильтр Джексона выглядит следующим образом:

private SimpleBeanPropertyFilter filter() {
    return new SimpleBeanPropertyFilter() {
        @Override
        public void serializeAsField(Object pojo, JsonGenerator jgen, SerializerProvider provider, PropertyWriter writer) throws Exception {
            String resourceMandatoryRole = getRoleBasedOnFilterableAnnotation(pojo);
            List<String> fieldMandatoryRoles = getRoleBasedOnFilterByAnnotation(writer);
            if (fieldMandatoryRoles.isEmpty() || fieldMandatoryRoles.contains(resourceMandatoryRole) ) {
                super.serializeAsField(pojo, jgen, provider, writer);
            }
        }
    };
}

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

  1. было бы неплохо не создавать еще одну аннотацию, которая говорит @GoInside, чтобы помочь войти в дочерние классы
  2. Я нехотите использовать эти расширения для JsonFilter для исключения дочерних полей, как они выглядят как @JsonFilter ("Object.Object.Object.Object.field")

Есть идеи?

...