Как сделать трансформацию данных?
В ответе с базы данных у меня приходит:
[Order{date='2017-10-16 12:07:07', docTypesName='Приход', docId=564564867361367, image='https://www.komus.ru/medias/sys_master/root/hd3/h93/9286922043422.jpg', name='Молочный Изюм 100', price=102.0, quantity=45, removed=0}, Order{date='2017-10-16 12:07:07', docTypesName='Приход', docId=564564867361367, image='https://mariupolcena.com/files/products/9ff44136e6ccb0afb404ad26f727e67d.jpeg', name='Русская картошка чедар 50', price=46.3, quantity=45, removed=0}, Order{date='2017-10-16 12:07:07', docTypesName='Расход', docId=564564867361367, image='https://mariupolcena.com/files/products/9ff44136e6ccb0afb404ad26f727e67d.jpeg', name='Русская картошка чедар 50', price=46.3, quantity=45, removed=0}, Order{date='2017-11-29 17:26:57', docTypesName='Расход', docId=564564867361365, image='https://www.komus.ru/medias/sys_master/root/hd3/h93/9286922043422.jpg', name='Молочный Изюм 100', price=102.0, quantity=6, removed=0}]
jackson-databind в Spring автоматически выполняет сериализацию.
Его JSON представление:
[
{
"date": "2017-10-16 12:07:07",
"docTypesName": "Приход",
"docId": 564564867361367,
"image": "https://www.komus.ru/medias/sys_master/root/hd3/h93/9286922043422.jpg",
"name": "Молочный Изюм 100",
"price": 102,
"quantity": 45,
"removed": 0
},
{
"date": "2017-10-16 12:07:07",
"docTypesName": "Приход",
"docId": 564564867361367,
"image": "https://mariupolcena.com/files/products/9ff44136e6ccb0afb404ad26f727e67d.jpeg",
"name": "Русская картошка чедар 50",
"price": 46.3,
"quantity": 45,
"removed": 0
},
{
"date": "2017-10-16 12:07:07",
"docTypesName": "Расход",
"docId": 564564867361367,
"image": "https://mariupolcena.com/files/products/9ff44136e6ccb0afb404ad26f727e67d.jpeg",
"name": "Русская картошка чедар 50",
"price": 46.3,
"quantity": 45,
"removed": 0
},
{
"date": "2017-11-29 17:26:57",
"docTypesName": "Расход",
"docId": 564564867361365,
"image": "https://www.komus.ru/medias/sys_master/root/hd3/h93/9286922043422.jpg",
"name": "Молочный Изюм 100",
"price": 102,
"quantity": 6,
"removed": 0
},
]
Подскажите, пожалуйста, как правильно сделать преобразование данных, чтобы получить следующую структуру (JSON представление):
[
{
"date": "2017-10-16",
documents: [
{
date: "2017-10-16 12:07:07",
docId: "564564867361367",
docTypesName: "Приход",
products: [
{
"image": "https://www.komus.ru/medias/sys_master/root/hd3/h93/9286922043422.jpg",
"name": "Молочный Изюм 100",
"price": 102,
"quantity": 45,
},
{
"image": "https://mariupolcena.com/files/products/9ff44136e6ccb0afb404ad26f727e67d.jpeg",
"name": "Русская картошка чедар 50",
"price": 46.3,
"quantity": 45,
}
]
},
{
"date": "2017-10-16 12:07:07",
"docId": 564564867361367,
"docTypesName": 'Расход',
"products": [
{
"image": "https://mariupolcena.com/files/products/9ff44136e6ccb0afb404ad26f727e67d.jpeg",
"name": "Русская картошка чедар 50",
"price": 46.3,
"quantity": 45,
}
]
}
]
},
{
"date": "2017-11-29",
"documents": [
{
"date": "2017-11-29 17:26:57",
"docId": 564564867361365,
"docTypesName": 'Расход',
"products": [
{
"image": "https://www.komus.ru/medias/sys_master/root/hd3/h93/9286922043422.jpg",
"name": "Молочный Изюм 100",
"price": 102,
"quantity": 6,
}
]
}
]
}
]
Ниже я описал класс, который формирует исходную структуру данных: Order.java
package main.java;
import java.util.ArrayList;
import java.util.List;
public class Order {
private String date;
private String docTypesName;
private String docId;
private String image;
private String name;
private double price;
private int quantity;
private int removed;
public Order(String date, String docTypesName, String docId, String image, String name, double price, int quantity, int removed) {
this.date = date;
this.docTypesName = docTypesName;
this.docId = docId;
this.image = image;
this.name = name;
this.price = price;
this.quantity = quantity;
this.removed = removed;
}
@Override
public String toString() {
return "Order{" +
"date='" + date + '\'' +
", docTypesName='" + docTypesName + '\'' +
", docId=" + docId +
", image='" + image + '\'' +
", name='" + name + '\'' +
", price=" + price +
", quantity=" + quantity +
", removed=" + removed +
'}';
}
}
class Test2 {
public static void main(String[] args) {
Order order = new Order("2017-10-16 12:07:07",
"Приход",
"564564867361367",
"https://www.komus.ru/medias/sys_master/root/hd3/h93/9286922043422.jpg",
"Молочный Изюм 100",
102,
45,
0);
Order order2 = new Order("2017-10-16 12:07:07",
"Приход",
"564564867361367",
"https://mariupolcena.com/files/products/9ff44136e6ccb0afb404ad26f727e67d.jpeg",
"Русская картошка чедар 50",
46.3,
45,
0);
Order order3 = new Order("2017-10-16 12:07:07",
"Расход",
"564564867361367",
"https://mariupolcena.com/files/products/9ff44136e6ccb0afb404ad26f727e67d.jpeg",
"Русская картошка чедар 50",
46.3,
45,
0);
Order order4 = new Order("2017-11-29 17:26:57",
"Расход",
"564564867361365",
"https://www.komus.ru/medias/sys_master/root/hd3/h93/9286922043422.jpg",
"Молочный Изюм 100",
102,
6,
0);
List<Order> orderList = new ArrayList<>();
orderList.add(order);
orderList.add(order2);
orderList.add(order3);
orderList.add(order4);
System.out.println(orderList);
}
}
Ответы (2 шт):
Автор решения: Alexandr
→ Ссылка
Вам необходимо ввести дополнительные три сущности, например, как в примере ниже - Day, Document, Item.
package com.somepackage;
import lombok.Builder;
import lombok.Getter;
import lombok.ToString;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@ToString
@Builder
@Getter
public class Order {
private final LocalDateTime date;
private final String docTypeName;
private final String docId;
private final String image;
private final String name;
private final double price;
private final int quantity;
private final boolean removed;
}
@ToString
@Builder
@Getter
class Item {
private final String image;
private final String name;
private final Double price;
private final Integer quantity;
}
@ToString
@Builder
@Getter
class Doc {
private final LocalDateTime date;
private final String docId;
private final String docTypeName;
private final List<Item> items;
}
@ToString
@Builder
@Getter
class Day {
private final LocalDate date;
private final List<Doc> documents;
}
class Test2 {
public static void main(String[] args) {
List<Order> orders =
Stream.of(
Order.builder()
.date(LocalDateTime.of(2017, 10, 16, 12, 7, 7))
.docTypeName("Приход")
.docId("564564867361367")
.image("https://www.komus.ru/medias/sys_master/root/hd3/h93/9286922043422.jpg")
.name("Молочный Изюм 100")
.price(102)
.quantity(45)
.removed(false)
.build(),
Order.builder()
.date(LocalDateTime.of(2017, 10, 16, 12, 7, 7))
.docTypeName("Приход")
.docId("564564867361367")
.image("https://mariupolcena.com/files/items/9ff44136e6ccb0afb404ad26f727e67d.jpeg")
.name("Русская картошка чедар 50")
.price(46.3)
.quantity(45)
.removed(false)
.build(),
Order.builder()
.date(LocalDateTime.of(2017, 10, 16, 12, 7, 7))
.docTypeName("Расход")
.docId("564564867361367")
.image("https://mariupolcena.com/files/items/9ff44136e6ccb0afb404ad26f727e67d.jpeg")
.name("Русская картошка чедар 50")
.price(46.3)
.quantity(45)
.removed(false)
.build(),
Order.builder()
.date(LocalDateTime.of(2017, 11, 29, 17, 26, 57))
.docTypeName("Расход")
.docId("564564867361365")
.image("https://www.komus.ru/medias/sys_master/root/hd3/h93/9286922043422.jpg")
.name("Молочный Изюм 100")
.price(102)
.quantity(6)
.removed(false)
.build()
).collect(Collectors.toList());
List<Day> days = new ArrayList<>();
for (Order order : orders) {
LocalDate date =
order.getDate().toLocalDate();
Day day =
days.stream()
.filter(d -> d.getDate().equals(date))
.findFirst()
.orElseGet(() -> {
Day newDay =
Day.builder()
.date(date)
.documents(new ArrayList<>())
.build();
days.add(newDay);
return newDay;
});
String docId =
order.getDocId();
String docTypeName =
order.getDocTypeName();
Doc doc =
day.getDocuments().stream()
.filter(d ->
d.getDocId().equals(docId) &&
d.getDocTypeName().equals(docTypeName))
.findFirst()
.orElseGet(() -> {
Doc newDoc =
Doc.builder()
.date(order.getDate())
.docId(docId)
.docTypeName(docTypeName)
.items(new ArrayList<>())
.build();
day.getDocuments().add(newDoc);
return newDoc;
});
String itemName =
order.getName();
doc.getItems().stream()
.filter(p -> p.getName().equals(itemName))
.findFirst()
.ifPresentOrElse(
p -> {
throw new IllegalArgumentException();
},
() -> {
Item newItem =
Item.builder()
.name(itemName)
.image(order.getImage())
.quantity(order.getQuantity())
.price(order.getPrice())
.build();
doc.getItems().add(newItem);
});
}
System.out.println(days);
}
}
Автор решения: Дмитрий
→ Ссылка
Я бы лучше прокинул через хешированную коллекцию по одной простой причине - читаемость кода. Это выглядит несоизмеримо проще:
public static Collection<OrderTarget> convert(List<Order> orders) {
return convert(orders.toArray(new Order[orders.size()]));
}
public static Collection<OrderTarget> convert(Order[] orders) {
Map<Document, Document> documents = new HashMap<>();
for (Order order : orders) {
Document doc = new Document(order);
if (documents.containsKey(doc)) documents.get(doc).addProduct(new Product(order));
else documents.put(doc, doc.addProduct(new Product(order)));
}
Map<LocalDate ,OrderTarget> orderTargets = new HashMap<>();
for (Document document : documents.values()) {
LocalDate date = document.getDate().toLocalDate();
if (orderTargets.containsKey(date)) orderTargets.get(date).addDocument(document);
else orderTargets.put(date, new OrderTarget(date, document));
}
return orderTargets.values();
}
@lombok.Data
@lombok.NoArgsConstructor
@lombok.AllArgsConstructor
public class Order {
private String date;
private String docTypesName;
private String docId;
private String image;
private String name;
private double price;
private int quantity;
private int removed;
}
@lombok.Data
@lombok.NoArgsConstructor
class OrderTarget {
public LocalDate date;
public List<Document> documents = new ArrayList<>();
public OrderTarget(LocalDate date, Document document) {
this.date = date;
this.documents.add(document);
}
public OrderTarget addDocument(Document document) {
documents.add(document);
return this;
}
}
@lombok.Data
@lombok.NoArgsConstructor
@lombok.EqualsAndHashCode(exclude = "products")
class Document {
private final static DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
public LocalDateTime date;
public String docId;
public String docTypesName;
public List<Product> products = new ArrayList<>();
public Document(Order order) {
this.date = LocalDateTime.parse(order.getDate(), FORMATTER);
this.docId = order.getDocId();
this.docTypesName = order.getDocTypesName();
}
public Document addProduct(Product product) {
products.add(product);
return this;
}
}
@lombok.Data
@lombok.NoArgsConstructor
class Product {
public String image;
public String name;
public double price;
public int quantity;
public Product(Order order) {
this.image = order.getImage();
this.name = order.getName();
this.price = order.getPrice();
this.quantity = order.getQuantity();
}
}