Для примера разберём такую задачу. Имеется класс UserDTO
, описывающий пользователя системы, у которого есть ряд булевых признаков (isActive, isStudent, isTeacher).
@Getter
@Setter
public class UserDTO {
private long userId;
private String userName;
private String firstName;
private String middleName;
private String lastName;
private boolean isActive;
private boolean isStudent;
private boolean isTeacher;
}
И рест-сервис, который возвращает пользователя в формате JSON.
@Component(service = UserController.class)
@Path("/user")
public class UserController {
@Reference(service = UserService.class)
UserService userService;
public UserController() {}
public UserController(UserService service) {
userService = service;
}
@GET
@Path("/")
@Produces(MediaType.APPLICATION_JSON)
public Response getCurrentUser(@Context HttpServletRequest request) throws Exception {
UserDTO user = userService.getUserDTO(PortalUtil.getUser(request));
return Response.ok().entity(user).build();
}
}
На стороне клиента фронт с помощью запроса получает пользователя и в зависимости от наличия у него признака student или teacher отображает разный контент.
<p>
Вы вошли как {currentUser?.fullName} ({currentUser?.userName})
{currentUser.isTeacher ? ", преподаватель" : ""}
{currentUser.isStudent ? ", студент" : ""}
</p>
С какой проблемой мы можем столкнуться? Мы ожидаем, что имена полей в ответе сервера будут соответствовать именам полей в UserDTO, но это не так. На деле JSON объект будет выглядеть так:
{
"userId":35970,
"userName":"teacher",
"firstName":"Вениамин",
"middleName":"Станиславович",
"lastName":"Обводный",
"active":true,
"student":false,
"teacher":false,
}
Использованные нами аннотации @Getter
и @Setter
автоматически удалили is из имён полей при генерации get* и set* методов (например, setActive для поля isActive), а Jackson сгенерировал по ним поля JSON объекта, удалив приставку get/set.
Существует возможность задать имена полей итогового JSON явно с помощью аннотаций. Для этого нужно добавить в проект зависимость (ниже пример для Gradle на котлине).
compileOnly("com.fasterxml.jackson.core:jackson-databind:2.10.3")
Версию Jackson следует подсмотреть в исходниках Liferay (в моём случае версии 7.3.4), иначе зависимость не будет найдена.
https://github.com/liferay/liferay-portal/blob/7.3.4-ga5/modules/apps/portal-remote/portal-remote-jaxrs-whiteboard-jaxb-json/build.gradle
Добавляем аннотации.
@Getter
@Setter
public class UserDTO {
private long userId;
private String userName;
private String firstName;
private String middleName;
private String lastName;
@JsonProperty("isActive")
private boolean isActive;
@JsonProperty("isStudent")
private boolean isStudent;
@JsonProperty("isTeacher")
private boolean isTeacher;
}
Теперь объект сериализуется так, как нам хотелось бы.
{
"userId":35970,
"userName":"teacher",
"firstName":"Вениамин",
"middleName":"Станиславович",
"lastName":"Обводный",
"isActive":true,
"isStudent":false,
"isTeacher":false,
}
Основной подводный камень в данном случае - поиск правильной версии зависимости. Не стоит пытаться делать зависимость уровня implementation и тащить её вместе с модулем, т.к. это может привести к другим ошибкам неразрешённых зависимостей, куда проще использовать библиотеки, уже имеющиеся в Liferay.