Skip to content

Commit e751a10

Browse files
committed
feat: Add record mapping and pattern matching tests
This commit adds two new tests to demonstrate advanced usage of the JSON library with modern Java features: - `JsonPatternMatchingTests.java`: Showcases how to use pattern matching with `switch` expressions to elegantly handle different `JsonValue` types, thanks to the `JsonValue` sealed interface. - `JsonRecordMappingTests.java`: Provides a comprehensive example of mapping a complex domain model (represented by a sealed interface and records) to and from the `JsonValue` hierarchy. This demonstrates a full serialization and deserialization cycle.
1 parent e9c9050 commit e751a10

File tree

1 file changed

+145
-0
lines changed

1 file changed

+145
-0
lines changed
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
2+
package jdk.sandbox.internal.util.json;
3+
4+
import jdk.sandbox.java.util.json.Json;
5+
import jdk.sandbox.java.util.json.JsonArray;
6+
import jdk.sandbox.java.util.json.JsonNumber;
7+
import jdk.sandbox.java.util.json.JsonObject;
8+
import jdk.sandbox.java.util.json.JsonString;
9+
import jdk.sandbox.java.util.json.JsonValue;
10+
import org.junit.jupiter.api.Test;
11+
12+
import java.util.Arrays;
13+
import java.util.LinkedHashMap;
14+
import java.util.List;
15+
import java.util.Map;
16+
import java.util.stream.Collectors;
17+
18+
import static org.assertj.core.api.Assertions.assertThat;
19+
20+
public class JsonRecordMappingTests {
21+
22+
// 1. Define the Domain Model using a Sealed Interface and Records
23+
public sealed interface Ecommerce permits Customer, Product, LineItem, Order {
24+
}
25+
26+
public record Customer(String name, String email) implements Ecommerce {
27+
}
28+
29+
public record Product(String sku, String name, double price) implements Ecommerce {
30+
}
31+
32+
public record LineItem(Product product, int quantity) implements Ecommerce {
33+
}
34+
35+
public record Order(String orderId, Customer customer, List<LineItem> items) implements Ecommerce {
36+
}
37+
38+
// 2. Implement Record-to-JSON Mapping
39+
private JsonValue toJon(Ecommerce domainObject) {
40+
return switch (domainObject) {
41+
case Order o -> {
42+
Map<String, JsonValue> map = new LinkedHashMap<>();
43+
map.put("type", JsonString.of("order"));
44+
map.put("orderId", JsonString.of(o.orderId()));
45+
map.put("customer", toJon(o.customer()));
46+
map.put("items", JsonArray.of(o.items().stream().map(this::toJon).collect(Collectors.toList())));
47+
yield JsonObject.of(map);
48+
}
49+
case Customer c -> {
50+
Map<String, JsonValue> map = new LinkedHashMap<>();
51+
map.put("type", JsonString.of("customer"));
52+
map.put("name", JsonString.of(c.name()));
53+
map.put("email", JsonString.of(c.email()));
54+
yield JsonObject.of(map);
55+
}
56+
case LineItem li -> {
57+
Map<String, JsonValue> map = new LinkedHashMap<>();
58+
map.put("type", JsonString.of("lineItem"));
59+
map.put("product", toJon(li.product()));
60+
map.put("quantity", JsonNumber.of(li.quantity()));
61+
yield JsonObject.of(map);
62+
}
63+
case Product p -> {
64+
Map<String, JsonValue> map = new LinkedHashMap<>();
65+
map.put("type", JsonString.of("product"));
66+
map.put("sku", JsonString.of(p.sku()));
67+
map.put("name", JsonString.of(p.name()));
68+
map.put("price", JsonNumber.of(p.price()));
69+
yield JsonObject.of(map);
70+
}
71+
};
72+
}
73+
74+
// 3. Implement JSON-to-Record Mapping
75+
private Ecommerce toDomain(JsonValue jsonValue) {
76+
if (!(jsonValue instanceof JsonObject jsonObject)) {
77+
throw new IllegalArgumentException("Expected a JsonObject");
78+
}
79+
80+
Map<String, JsonValue> members = jsonObject.members();
81+
String type = ((JsonString) members.get("type")).value();
82+
83+
return switch (type) {
84+
case "order" -> {
85+
String orderId = ((JsonString) members.get("orderId")).value();
86+
Customer customer = (Customer) toDomain(members.get("customer"));
87+
List<LineItem> items = ((JsonArray) members.get("items")).values().stream()
88+
.map(item -> (LineItem) toDomain(item))
89+
.collect(Collectors.toList());
90+
yield new Order(orderId, customer, items);
91+
}
92+
case "customer" -> {
93+
String name = ((JsonString) members.get("name")).value();
94+
String email = ((JsonString) members.get("email")).value();
95+
yield new Customer(name, email);
96+
}
97+
case "lineItem" -> {
98+
Product product = (Product) toDomain(members.get("product"));
99+
int quantity = ((JsonNumber) members.get("quantity")).toNumber().intValue();
100+
yield new LineItem(product, quantity);
101+
}
102+
case "product" -> {
103+
String sku = ((JsonString) members.get("sku")).value();
104+
String name = ((JsonString) members.get("name")).value();
105+
double price = ((JsonNumber) members.get("price")).toNumber().doubleValue();
106+
yield new Product(sku, name, price);
107+
}
108+
default -> throw new IllegalStateException("Unexpected value: " + type);
109+
};
110+
}
111+
112+
113+
@Test
114+
void testEcommerceDagMapping() {
115+
// Step 1: Create the object graph
116+
var customer = new Customer("John Doe", "[email protected]");
117+
var product1 = new Product("SKU-001", "Laptop", 1200.00);
118+
var product2 = new Product("SKU-002", "Mouse", 25.00);
119+
var order = new Order("ORD-12345", customer, Arrays.asList(
120+
new LineItem(product1, 1),
121+
new LineItem(product2, 2)
122+
));
123+
124+
// Step 2: Convert to JSON
125+
JsonObject jsonOrder = (JsonObject) toJon(order);
126+
String jsonString = jsonOrder.toString();
127+
128+
// For demonstration, let's parse it back with the library's parser
129+
JsonParser parser = new JsonParser(jsonString.toCharArray());
130+
JsonObject parsedJsonOrder = (JsonObject) parser.parseRoot();
131+
132+
// Step 3: Convert back to a record
133+
Order reconstructedOrder = (Order) toDomain(parsedJsonOrder);
134+
135+
// Step 4: Assert equality
136+
assertThat(reconstructedOrder).isEqualTo(order);
137+
138+
// You can also assert individual fields to be sure
139+
assertThat(reconstructedOrder.orderId()).isEqualTo("ORD-12345");
140+
assertThat(reconstructedOrder.customer().name()).isEqualTo("John Doe");
141+
assertThat(reconstructedOrder.items()).hasSize(2);
142+
assertThat(reconstructedOrder.items().get(0).product().name()).isEqualTo("Laptop");
143+
assertThat(reconstructedOrder.items().get(1).quantity()).isEqualTo(2);
144+
}
145+
}

0 commit comments

Comments
 (0)