Решение 1: Пользовательский сериализатор
Подробности: вы можете сказать Джексону, как сериализовать ваш объект. Если вы хотите сериализовать его всегда одним и тем же способом, вы можете указать на уровне класса, что он всегда должен использовать этот сериализатор. Если вы считаете, что вам понадобятся другие сериализаторы, вы должны вместо этого настроить свой objectMapper:
ObjectMapper mapper = new ObjectMapper ();
SimpleModule module = new SimpleModule();
module.addSerializer(Attachment.class, new AttachmentSerializer());
Сериализатор вложений:
public class AttachmentSerializer extends StdSerializer<Attachment> {
public AttachmentSerializer() {
this(null);
}
public AttachmentSerializer(Class<Attachment> t) {
super(t);
}
@Override
public void serialize(
Attachment attachment, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonProcessingException {
jgen.writeStartObject();
jgen.writeArrayFieldStart("attachments");
for (AttachmentID attachmentID : attachment.getId()) {
jgen.writeStartObject();
jgen.writeStringField("id", attachmentID.getAttachmentID());
jgen.writeEndObject();
}
jgen.writeStartObject();
jgen.writeStringField("filename", attachment.getFilename());
jgen.writeStringField("filetype", attachment.getFiletype());
jgen.writeEndObject();
jgen.writeEndArray();
jgen.writeEndObject();
}
}
и добавить:
@JsonSerialize(using = AttachmentSerializer.class)
@JsonPropertyOrder({"id", "filename", "filetype"})
public class Attachment {
Я добавил собственный сериализатор только в ваш класс Attachment, потому что он единственный, который нуждается в специальной обработке.
Решение 2: создайте пользовательский RecordAttachmentDTO с необходимыми целевыми полями и сериализуйте его вместо RecordAttachment.
public class RecordAttachmentDTO {
private String id;
private List<Map<String, String>> attachments = new ArrayList<>();
public RecordAttachmentDTO(RecordAttachment recordAttachment) {
this.id = recordAttachment.getId();
List<Attachment> attachments = recordAttachment.getAttachments();
attachments.forEach(attachment -> addAttachment(attachment));
}
private void addAttachment(Attachment attachment) {
attachment.getId().forEach(attachmentID -> attachments.add(Collections.singletonMap("id", attachmentID.getAttachmentID())));
Map<String, String> fileMap = new HashMap<>();
fileMap.put("filename", attachment.getFilename());
fileMap.put("fileType", attachment.getFiletype());
attachments.add(fileMap);
}
public List<Map<String, String>> getAttachments() {
return attachments;
}
public void setAttachments(List<Map<String, String>> attachments) {
this.attachments = attachments;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
Это решение поможет вам при необходимости иметь несколько сериализаторов. Это решение в основном является оберткой вашего оригинального объекта. Вместо того, чтобы сериализовать исходный объект, вы вместо этого сериализуете оболочку.
Решение 3: создание объектов JsonNode
public static String serializeRecordAttachment(RecordAttachment recordAttachment) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
ObjectNode recordNode = objectMapper.createObjectNode();
recordNode.put("id", recordAttachment.getId());
List<Attachment> attachments = recordAttachment.getAttachments();
recordNode.set("attachments",
createAttachmentNode(objectMapper,attachments));
return objectMapper.writeValueAsString(recordNode.toString);
}
private static ArrayNode createAttachmentNode(ObjectMapper objectMapper, List<Attachment> attachments) {
ArrayNode attachmentsNode = objectMapper.createArrayNode();
attachments.forEach(attachment -> addAttachment(objectMapper, attachmentsNode, attachment);
return attachmentsNode;
}
private static void addAttachment(ObjectMapper objectMapper, ArrayNode attachmentsNode, Attachment attachment) {
attachment.getId().forEach(idField -> {
ObjectNode attchIdNode = objectMapper.createObjectNode();
attchIdNode.put("id", idField.getAttachmentID());
attachmentsNode.add(attchIdNode);
});
ObjectNode fileNode = objectMapper.createObjectNode();
fileNode.put("filename", attachment.getFilename());
fileNode.put("filetype", attachment.getFiletype());
attachmentsNode.add(fileNode);
}
Это решение аналогично решению 2, преимущество в том, что вам не нужен объект-оболочка.