Я стараюсь избегать использования антипаттерна DTO, когда вызываются разные EndPoint, где каждый возвращает отдельное представление одной и той же сущности. Я хотел бы воспользоваться сериализацией, которую выполняет Джексон, когда я возвращаю сущность в Rest EndPoint. Это означает, что сериализация выполняется только один раз, а не дважды, как это было бы с DTO (объект для DTO и DTO для Json):
Пример EndPoints:
@GetMapping("/events")
public ResponseEntity<List<Event>> getAllEvents(){
try {
List<Event> events = (List<Event>) eventsRepository.findAll();
return new ResponseEntity<List<Event>>(
events, HttpStatus.OK);
}catch(IllegalArgumentException e) {
return new ResponseEntity<List<Event>>(HttpStatus.BAD_REQUEST);
}
}
@GetMapping("/events/{code}")
public ResponseEntity<Event> retrieveEvent(@PathVariable String code){
Optional<Event> event = eventsRepository.findByCode(code);
return event.isPresent() ?
new ResponseEntity<Event>(event.get(), HttpStatus.OK) :
new ResponseEntity<Event>(HttpStatus.BAD_REQUEST);
}
Сериализатор (класс, который расширяет StdSerializer):
@Override
public void serialize(Event value, JsonGenerator gen,
SerializerProvider provider) throws IOException {
if(firstRepresentation) {
//First Representation
gen.writeStartObject();
gen.writeNumberField("id", value.getId());
gen.writeObjectField("creation", value.getCreation());
gen.writeObjectFieldStart("event_tracks");
for (EventTrack eventTrack : value.getEventsTracks()) {
gen.writeNumberField("id", eventTrack.getId());
gen.writeObjectField("startTime", eventTrack.getStartTime());
gen.writeObjectField("endTime", eventTrack.getEndTime());
gen.writeNumberField("priority", eventTrack.getPriority());
gen.writeObjectFieldStart("user");
gen.writeNumberField("id", eventTrack.getUser().getId());
gen.writeEndObject();
gen.writeObjectFieldStart("state");
gen.writeNumberField("id", eventTrack.getState().getId());
gen.writeStringField("name", eventTrack.getState().getName());
gen.writeEndObject();
}
gen.writeEndObject();
gen.writeEndObject();
}else if(secondRepresentation) {
//Second Representation
}
}
Сущность:
@JsonSerialize(using = EventSerializer.class)
@RequiredArgsConstructor
@Getter
@Setter
public class Event implements Comparable<Event>{
private Long id;
@JsonIgnore
private String code;
private Timestamp creation;
@NonNull
private String description;
@JsonUnwrapped
@NonNull
private EventSource eventSource;
@NonNull
private String title;
@NonNull
private Category category;
@NonNull
@JsonProperty("event_tracks")
private List<EventTrack> eventsTracks;
@JsonProperty("protocol_tracks")
private List<ProtocolTrack> protocolTracks;
public void addEventTrack(@NonNull EventTrack eventTracks) {
eventsTracks.add(eventTracks);
}
@JsonIgnore
public EventTrack getLastEventTrack() {
return eventsTracks.get(eventsTracks.size() - 1);
}
@JsonIgnore
public int getLastPriority() {
return getLastEventTrack().getPriority();
}
public void generateUUIDCode() {
this.code = UUID.randomUUID().toString();
}
@Override
public int compareTo(Event o) {
return this.getLastPriority() - o.getLastPriority();
}
}
Итак, пока я удалось сериализовать тип представления с помощью класса, расширяющего StdDeserializer, но это не дает мне гибкости для расширения представлений одних и тех же атрибутов сущности несколькими способами. Хотя я пробовал это с аннотациями Json, но я понимаю, что чем больше представлений у класса сущностей, тем он может быть очень сложным, чем просто. Может быть, какая-то идея, как я мог это сделать.
Спасибо.