Как изменить JsonView для конкретных свойств

Привет, у меня есть несколько объектов пользовательского интерфейса, которые встроены друг в друга. Пример № 1:

class CarUI {
  public UserUI user;
  public UserUI agent;
  ....
  public UserUI getUser() {
    return user;
  }
  public UserUI getAgent() {
    return agent;
  }
}
class UserUI {
  @JsonView({Views.Public.class,Views.Private.class})
  public String name;
  @JsonView({Views.Private.class})
  public String phone;
  ...
}

Как вы можете видеть, если я сериализую UserUI как Public, я выставлю только имя, но для private я выставлю все поля.

Вот мой вопрос: когда я сериализую объект CarUI, я хочу выставить только имя для "пользователя" и имя + телефон для "агента". По сути это означает, что в getter для getUser() я хочу изменить JsonView на Views.Public.class, а для getAgent() я хочу изменить его на Views.Private.class

Есть ли способ перезаписать JsonView в получателях, чтобы теперь вся иерархия возвращаемого объекта сериализовалась с использованием этого нового JsonView?

Отредактировано Как указано ниже, вы можете решить мой пример № 1 с наследованием JsonView. Как насчет более общего. Вот пример № 2:

class CarUI {
  public UserUI user;
  public UserUI agent;
  ....
  public UserUI getUser() {
    return user;
  }
  public UserUI getAgent() {
    return agent;
  }
}
class UserUI {
  @JsonView({Views.Public.class,Views.Private.class})
  public String name;
  @JsonView({Views.Private.class})
  public String phone;
  @JsonView({Views.Public.class})
  public String avatarUrl;
  ...
}

В этом примере я хотел бы отобразить имя + телефон для агента и имя +avatarUrl для пользователя.

2 ответа

Решение

@JsonView принимает наследование. Поля Views.Private расширяют поля Views.Public. Это означает, что сериализация Views.Private также будет искать аннотации Views.Public.

public Views {
    public Public {}
    public Private extends Public {}
}

class CarUI {
  public UserUI user;
  public UserUI agent;
  ....
  @JsonView(Views.Public.class)
  public UserUI getUser() {
    return user;
  }
  @JsonView(Views.Private.class)
  public UserUI getAgent() {
    return agent;
  }
}

class UserUI {
  @JsonView(Views.Public.class)
  public String name;
  @JsonView(Views.Private.class)
  public String phone;
  ...
}

Для примера № 2

Вы можете ввести несколько классов, таких как:

public Views {
    public Public {}
    public Private1 extends Public {}
    public Private2 extends Public {}
}

class CarUI {
  public UserUI user;
  public UserUI agent;
  ....
  public UserUI getUser() {
    return user;
  }
  public UserUI getAgent() {
    return agent;
  }
}
class UserUI {
  @JsonView(Views.Public.class)
  public String name;
  @JsonView({Views.Private1.class})
  public String phone;
  @JsonView({Views.Private2.class})
  public String avatarUrl;
  ...
}

Или вы можете использовать свойства без просмотра и не использовать наследование:

public Views {
    public Public {}
    public Private {}
}

class CarUI {
  public UserUI user;
  public UserUI agent;
  ....
  public UserUI getUser() {
    return user;
  }
  public UserUI getAgent() {
    return agent;
  }
}
class UserUI {
  // This one is view-less shows every time unless you specificy
  public String name;
  @JsonView({Views.Private.class})
  public String phone;
  @JsonView({Views.Public.class})
  public String avatarUrl;
  ...
}

...
// If you want to hide view-less properties, default is true 
objectMapper.configure(SerializationConfig.Feature.DEFAULT_VIEW_INCLUSION, false); 
...

Просто нашел более общий случай, если кому-то нужно. По сути, вы можете преобразовать свое свойство внутри геттера, используя другой JsonView, как таковой:

  @JsonView({ Views.Detail.class})
  public JsonNode getAgent() throws IOException {
      ObjectMapper mapper = new ObjectMapper();
      String json = mapper.writerWithView(Views. Private.class).writeValueAsString(agent);
      return mapper.readTree(json);
  }
Другие вопросы по тегам