Используя Джексона, как я могу сериализовать результат параметризованного вызова метода для фильтрации списка дочерних объектов? - PullRequest
0 голосов
/ 17 ноября 2018

Я использую SpringBoot / Hibernate для моей инфраструктуры приложений. У меня есть класс, который содержит загрузку параметров для моего приложения. У него есть некоторые параметры, которые применяются всегда, а некоторые отличаются в зависимости от того, над чем вы работаете (параметры для каждого проекта). Это было смоделировано как родительский класс, который содержит коллекцию дочерних классов, в результате чего один и только один экземпляр дочерних элементов будет «активным» в любой момент времени, в зависимости от некоторого контекста (например, над проектом, над которым ведется работа, но с реальным case имеет несколько более сложную логику для определения «активного» потомка).

Почти во всех случаях я хочу сериализовать только одного потомка, который применим в данный момент, но в некоторых случаях я хочу сериализовать весь набор.

Я могу добиться этого используя следующее:

public class Parent {

    @JsonView(JsonViews.AllChildren.class)
    private Set<Child> children= new HashSet<>();

    @JsonIgnore
    private Context context;

    public void setContext (Context context) {
        this.context = context;
    }

    @JsonView(JsonViews.ActiveChild.class)
    @JsonProperty("activeChild")
    public Child getActiveChild() {

        for (Child child : this.children) {
            if (someFunction(this.context)) {
                return child;
            }
        }

        return null;
    }

Тогда в моем контроллере я могу сделать:

@GetMapping("/parent")
@JsonView(JsonViews.AllChildren.class)
public Parent getParent() {
    return ParentService.getParent();
}

@GetMapping("/parent/{context}")
@JsonView(JsonViews.ActiveChild.class)
public Parent getParentWithContext(PathVariable final String contextName)) {
    Context context = ContextService.getContextByName(contextName);
    Parent parent = ParentService.getParent();
    parent.setContext(context);
    return Parent;
}

Работает хорошо, но вводит некоторое состояние (настройка контекста в Parent), которого я хочу избежать.

Итак, теперь вопрос: как я могу сериализовать родительские / дочерние классы для удаления атрибута состояния, например, что-то вроде:

@JsonView(JsonViews.ActiveChild.class)
@JsonProperty("activeChild")
public Child getActiveChild(Context context) {

    for (Child child : this.children) {
        if (someFunction(context)) {
            return child;
        }
    }

    return null;
}

@GetMapping("/parent/{context}")
@JsonView(JsonViews.ActiveChild.class)
public Parent getParentWithContext(PathVariable final String contextName)) {
    Context context = ContextService.getContextByName(contextName);
    Parent parent = ParentService.getParent();

    // How to tell the Json serialization to pass the context to getActiveChild

    return Parent;
}

Все, что я обнаружил в сериализации Json Context, похоже, имеет фиксированный набор контекстов (поиск неизвестного списка) и может использоваться для добавления / удаления атрибутов из вывода вместо фильтрации данных.

Единственное решение, которое я нашел до сих пор, - это вызвать сам ObjectMapper для получения полной json-сериализации всех дочерних элементов, а затем удалить все, кроме того, которое я хочу вернуть. Но это означает, что у меня есть дубликаты наборов логики «Какой дочерний элемент активен для этого контекста» - один в классе Parent работает с объектами Parent и Child, а другой - в функции getParentWithContext, которая работает с представлением json. Есть ли что-нибудь лучшее, что я могу сделать, например,

  1. Сделайте какой-нибудь пользовательский сериализатор, который может каким-то образом вызвать метод getActiveChild на родительском объекте с переданным контекстом перед отображением результата, или
  2. Каким-то образом сделать контекст ThreadLocal, когда он установлен в вызове рендеринга?
  3. Каким-то образом создать новый класс, который расширяет мой родительский класс экземпляром класса Context в его конструкторе и возвращает его для сериализации Джексона?
  4. Создать клон Родителя, установить контекст на клоне, разрешить его сериализацию, а затем собрать мусор?
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...