Skip to content

Commit 1ffcc80

Browse files
committed
feat: sync API with latest upstream java.util.json and fix tests
1 parent 30fa53e commit 1ffcc80

File tree

31 files changed

+630
-1215
lines changed

31 files changed

+630
-1215
lines changed

README.md

Lines changed: 30 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@ JsonValue value = Json.parse(json);
4141

4242
// Access as map-like structure
4343
JsonObject obj = (JsonObject) value;
44-
String name = ((JsonString) obj.members().get("name")).value();
45-
int age = ((JsonNumber) obj.members().get("age")).intValue();
46-
boolean active = ((JsonBoolean) obj.members().get("active")).value();
44+
String name = ((JsonString) obj.members().get("name")).string();
45+
int age = Math.toIntExact(((JsonNumber) obj.members().get("age")).toLong());
46+
boolean active = ((JsonBoolean) obj.members().get("active")).bool();
4747
```
4848

4949
### Simple Record Mapping
@@ -58,56 +58,22 @@ JsonObject jsonObj = (JsonObject) Json.parse(userJson);
5858

5959
// Map to record
6060
User user = new User(
61-
((JsonString) jsonObj.members().get("name")).value(),
62-
((JsonNumber) jsonObj.members().get("age")).intValue(),
63-
((JsonBoolean) jsonObj.members().get("active")).value()
61+
((JsonString) jsonObj.members().get("name")).string(),
62+
Math.toIntExact(((JsonNumber) jsonObj.members().get("age")).toLong()),
63+
((JsonBoolean) jsonObj.members().get("active")).bool()
6464
);
6565

6666
// Convert records back to JSON
67-
JsonValue backToJson = Json.fromUntyped(Map.of(
68-
"name", user.name(),
69-
"age", user.age(),
70-
"active", user.active()
67+
JsonValue backToJson = JsonObject.of(Map.of(
68+
"name", JsonString.of(user.name()),
69+
"age", JsonNumber.of(user.age()),
70+
"active", JsonBoolean.of(user.active())
7171
));
7272

7373
// Covert back to a JSON string
7474
String jsonString = backToJson.toString();
7575
```
7676

77-
### Converting from Java Objects to JSON (`fromUntyped`)
78-
79-
```java
80-
// Convert standard Java collections to JsonValue
81-
Map<String, Object> data = Map.of(
82-
"name", "John",
83-
"age", 30,
84-
"scores", List.of(85, 92, 78)
85-
);
86-
JsonValue json = Json.fromUntyped(data);
87-
```
88-
89-
### Converting from JSON to Java Objects (`toUntyped`)
90-
91-
```java
92-
// Convert JsonValue back to standard Java types
93-
JsonValue parsed = Json.parse("{\"name\":\"John\",\"age\":30}");
94-
Object data = Json.toUntyped(parsed);
95-
// Returns a Map<String, Object> with standard Java types
96-
```
97-
98-
The conversion mappings are:
99-
- `JsonObject``Map<String, Object>`
100-
- `JsonArray``List<Object>`
101-
- `JsonString``String`
102-
- `JsonNumber``Number` (Long, Double, BigInteger, or BigDecimal)
103-
- `JsonBoolean``Boolean`
104-
- `JsonNull``null`
105-
106-
This is useful for:
107-
- Integrating with existing code that uses standard collections
108-
- Serializing/deserializing to formats that expect Java types
109-
- Working with frameworks that use reflection on standard types
110-
11177
### Realistic Record Mapping
11278

11379
A powerful feature is mapping between Java records and JSON:
@@ -124,28 +90,28 @@ Team team = new Team("Engineering", List.of(
12490
));
12591

12692
// Convert records to JSON
127-
JsonValue teamJson = Json.fromUntyped(Map.of(
128-
"teamName", team.teamName(),
129-
"members", team.members().stream()
130-
.map(u -> Map.of(
131-
"name", u.name(),
132-
"email", u.email(),
133-
"active", u.active()
134-
))
135-
.toList()
93+
JsonValue teamJson = JsonObject.of(Map.of(
94+
"teamName", JsonString.of(team.teamName()),
95+
"members", JsonArray.of(team.members().stream()
96+
.map(u -> JsonObject.of(Map.of(
97+
"name", JsonString.of(u.name()),
98+
"email", JsonString.of(u.email()),
99+
"active", JsonBoolean.of(u.active())
100+
)))
101+
.toList())
136102
));
137103

138104
// Parse JSON back to records
139105
JsonObject parsed = (JsonObject) Json.parse(teamJson.toString());
140106
Team reconstructed = new Team(
141-
((JsonString) parsed.members().get("teamName")).value(),
142-
((JsonArray) parsed.members().get("members")).values().stream()
107+
((JsonString) parsed.members().get("teamName")).string(),
108+
((JsonArray) parsed.members().get("members")).elements().stream()
143109
.map(v -> {
144110
JsonObject member = (JsonObject) v;
145111
return new User(
146-
((JsonString) member.members().get("name")).value(),
147-
((JsonString) member.members().get("email")).value(),
148-
((JsonBoolean) member.members().get("active")).value()
112+
((JsonString) member.members().get("name")).string(),
113+
((JsonString) member.members().get("email")).string(),
114+
((JsonBoolean) member.members().get("active")).bool()
149115
);
150116
})
151117
.toList()
@@ -182,10 +148,10 @@ Process JSON arrays efficiently with Java streams:
182148
```java
183149
// Filter active users from a JSON array
184150
JsonArray users = (JsonArray) Json.parse(jsonArrayString);
185-
List<String> activeUserEmails = users.values().stream()
151+
List<String> activeUserEmails = users.elements().stream()
186152
.map(v -> (JsonObject) v)
187-
.filter(obj -> ((JsonBoolean) obj.members().get("active")).value())
188-
.map(obj -> ((JsonString) obj.members().get("email")).value())
153+
.filter(obj -> ((JsonBoolean) obj.members().get("active")).bool())
154+
.map(obj -> ((JsonString) obj.members().get("email")).string())
189155
.toList();
190156
```
191157

@@ -198,9 +164,9 @@ try {
198164
JsonValue value = Json.parse(userInput);
199165
// Process valid JSON
200166
} catch (JsonParseException e) {
201-
// Handle malformed JSON with line/column information
202-
System.err.println("Invalid JSON at line " + e.getLine() +
203-
", column " + e.getColumn() + ": " + e.getMessage());
167+
// Handle malformed JSON with line/position information
168+
System.err.println("Invalid JSON at line " + e.getErrorLine() +
169+
", position " + e.getErrorPosition() + ": " + e.getMessage());
204170
}
205171
```
206172

index.html

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,8 @@ <h3>Simple Example</h3>
9595
JsonObject obj = (JsonObject) value;
9696

9797
// Access values
98-
String name = ((JsonString) obj.members().get("name")).value();
99-
int age = ((JsonNumber) obj.members().get("age")).toNumber().intValue();</code></pre>
98+
String name = ((JsonString) obj.members().get("name")).string();
99+
int age = Math.toIntExact(((JsonNumber) obj.members().get("age")).toLong());</code></pre>
100100

101101
<h2>Key Features</h2>
102102
<ul>
@@ -118,15 +118,15 @@ <h2>Record Mapping Example</h2>
118118
new User("Bob", "bob@example.com", false)
119119
));
120120

121-
JsonValue teamJson = Json.fromUntyped(Map.of(
122-
"teamName", team.teamName(),
123-
"members", team.members().stream()
124-
.map(u -> Map.of(
125-
"name", u.name(),
126-
"email", u.email(),
127-
"active", u.active()
128-
))
129-
.toList()
121+
JsonValue teamJson = JsonObject.of(Map.of(
122+
"teamName", JsonString.of(team.teamName()),
123+
"members", JsonArray.of(team.members().stream()
124+
.map(u -> JsonObject.of(Map.of(
125+
"name", JsonString.of(u.name()),
126+
"email", JsonString.of(u.email()),
127+
"active", JsonBoolean.of(u.active())
128+
)))
129+
.toList())
130130
));</code></pre>
131131

132132
<h2>Resources</h2>

json-java21-api-tracker/src/main/java/io/github/simbo1905/tracker/ApiTracker.java

Lines changed: 38 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -599,7 +599,7 @@ static JsonObject compareApis(JsonObject local, JsonObject upstream) {
599599
// Extract class name safely
600600
final var localClassName = local.members().get("className");
601601
final var className = localClassName instanceof JsonString js ?
602-
js.value() : "Unknown";
602+
js.string() : "Unknown";
603603

604604
diffMap.put("className", JsonString.of(className));
605605

@@ -612,7 +612,7 @@ static JsonObject compareApis(JsonObject local, JsonObject upstream) {
612612

613613
// Check if status is NOT_IMPLEMENTED (from parsing)
614614
if (upstream.members().containsKey("status")) {
615-
final var status = ((JsonString) upstream.members().get("status")).value();
615+
final var status = ((JsonString) upstream.members().get("status")).string();
616616
if ("NOT_IMPLEMENTED".equals(status)) {
617617
diffMap.put("status", JsonString.of("PARSE_NOT_IMPLEMENTED"));
618618
return JsonObject.of(diffMap);
@@ -681,11 +681,11 @@ static boolean compareModifiers(JsonObject local, JsonObject upstream, List<Json
681681
return false;
682682
}
683683

684-
final var localSet = localMods.values().stream()
685-
.map(v -> ((JsonString) v).value())
684+
final var localSet = localMods.elements().stream()
685+
.map(v -> ((JsonString) v).string())
686686
.collect(Collectors.toSet());
687-
final var upstreamSet = upstreamMods.values().stream()
688-
.map(v -> ((JsonString) v).value())
687+
final var upstreamSet = upstreamMods.elements().stream()
688+
.map(v -> ((JsonString) v).string())
689689
.collect(Collectors.toSet());
690690

691691
if (!localSet.equals(upstreamSet)) {
@@ -708,11 +708,11 @@ static boolean compareInheritance(JsonObject local, JsonObject upstream, List<Js
708708
return false;
709709
}
710710

711-
final var localTypes = localExtends.values().stream()
712-
.map(v -> normalizeTypeName(((JsonString) v).value()))
711+
final var localTypes = localExtends.elements().stream()
712+
.map(v -> normalizeTypeName(((JsonString) v).string()))
713713
.collect(Collectors.toSet());
714-
final var upstreamTypes = upstreamExtends.values().stream()
715-
.map(v -> normalizeTypeName(((JsonString) v).value()))
714+
final var upstreamTypes = upstreamExtends.elements().stream()
715+
.map(v -> normalizeTypeName(((JsonString) v).string()))
716716
.collect(Collectors.toSet());
717717

718718
if (!localTypes.equals(upstreamTypes)) {
@@ -786,8 +786,8 @@ static boolean compareMethods(JsonObject local, JsonObject upstream, List<JsonVa
786786
/// Compares method signatures
787787
static boolean compareMethodSignature(JsonObject localMethod, JsonObject upstreamMethod) {
788788
// Compare return types
789-
final var localReturn = normalizeTypeName(((JsonString) localMethod.members().get("returnType")).value());
790-
final var upstreamReturn = normalizeTypeName(((JsonString) upstreamMethod.members().get("returnType")).value());
789+
final var localReturn = normalizeTypeName(((JsonString) localMethod.members().get("returnType")).string());
790+
final var upstreamReturn = normalizeTypeName(((JsonString) upstreamMethod.members().get("returnType")).string());
791791
if (!localReturn.equals(upstreamReturn)) {
792792
return false;
793793
}
@@ -796,14 +796,14 @@ static boolean compareMethodSignature(JsonObject localMethod, JsonObject upstrea
796796
final var localParams = (JsonArray) localMethod.members().get("parameters");
797797
final var upstreamParams = (JsonArray) upstreamMethod.members().get("parameters");
798798

799-
if (localParams.values().size() != upstreamParams.values().size()) {
799+
if (localParams.elements().size() != upstreamParams.elements().size()) {
800800
return false;
801801
}
802802

803803
// Compare each parameter
804-
for (int i = 0; i < localParams.values().size(); i++) {
805-
final var localParam = normalizeTypeName(((JsonString) localParams.values().get(i)).value());
806-
final var upstreamParam = normalizeTypeName(((JsonString) upstreamParams.values().get(i)).value());
804+
for (int i = 0; i < localParams.elements().size(); i++) {
805+
final var localParam = normalizeTypeName(((JsonString) localParams.elements().get(i)).string());
806+
final var upstreamParam = normalizeTypeName(((JsonString) upstreamParams.elements().get(i)).string());
807807
if (!localParam.equals(upstreamParam)) {
808808
return false;
809809
}
@@ -848,11 +848,11 @@ static boolean compareConstructors(JsonObject local, JsonObject upstream, List<J
848848
return false;
849849
}
850850

851-
if (localConstructors.values().size() != upstreamConstructors.values().size()) {
851+
if (localConstructors.elements().size() != upstreamConstructors.elements().size()) {
852852
differences.add(JsonObject.of(Map.of(
853853
"type", JsonString.of("constructorsChanged"),
854-
"localCount", JsonNumber.of(localConstructors.values().size()),
855-
"upstreamCount", JsonNumber.of(upstreamConstructors.values().size())
854+
"localCount", JsonNumber.of(localConstructors.elements().size()),
855+
"upstreamCount", JsonNumber.of(upstreamConstructors.elements().size())
856856
)));
857857
return true;
858858
}
@@ -908,7 +908,7 @@ static JsonObject runFullComparison() {
908908
differences.add(diff);
909909

910910
// Count statistics
911-
final var status = ((JsonString) diff.members().get("status")).value();
911+
final var status = ((JsonString) diff.members().get("status")).string();
912912
switch (status) {
913913
case "MATCHING" -> matchingCount++;
914914
case "UPSTREAM_ERROR" -> missingUpstream++;
@@ -964,21 +964,21 @@ static String generateFingerprint(JsonObject report) {
964964
final var differences = (JsonArray) report.members().get("differences");
965965
final var stableLines = new ArrayList<String>();
966966

967-
for (final var diff : differences.values()) {
967+
for (final var diff : differences.elements()) {
968968
final var diffObj = (JsonObject) diff;
969-
final var status = ((JsonString) diffObj.members().get("status")).value();
969+
final var status = ((JsonString) diffObj.members().get("status")).string();
970970

971971
if (!"DIFFERENT".equals(status)) continue;
972972

973-
final var className = ((JsonString) diffObj.members().get("className")).value();
973+
final var className = ((JsonString) diffObj.members().get("className")).string();
974974
final var classDiffs = (JsonArray) diffObj.members().get("differences");
975975

976976
if (classDiffs != null) {
977-
for (final var change : classDiffs.values()) {
977+
for (final var change : classDiffs.elements()) {
978978
final var changeObj = (JsonObject) change;
979-
final var type = ((JsonString) changeObj.members().get("type")).value();
979+
final var type = ((JsonString) changeObj.members().get("type")).string();
980980
final var methodValue = changeObj.members().get("method");
981-
final var method = methodValue instanceof JsonString js ? js.value() : "";
981+
final var method = methodValue instanceof JsonString js ? js.string() : "";
982982
// Create stable line: "ClassName:changeType:methodName"
983983
stableLines.add(className + ":" + type + ":" + method);
984984
}
@@ -1013,7 +1013,7 @@ private static long getDifferentApiCount(JsonObject report) {
10131013
}
10141014
final var differentApiValue = summary.members().get("differentApi");
10151015
if (differentApiValue instanceof JsonNumber num) {
1016-
return num.toNumber().longValue();
1016+
return num.toLong();
10171017
}
10181018
return 0;
10191019
}
@@ -1027,10 +1027,10 @@ static String generateSummary(JsonObject report) {
10271027
final var summary = (JsonObject) report.members().get("summary");
10281028
final var differences = (JsonArray) report.members().get("differences");
10291029

1030-
final var totalClasses = ((JsonNumber) summary.members().get("totalClasses")).toNumber().longValue();
1031-
final var matchingClasses = ((JsonNumber) summary.members().get("matchingClasses")).toNumber().longValue();
1030+
final var totalClasses = ((JsonNumber) summary.members().get("totalClasses")).toLong();
1031+
final var matchingClasses = ((JsonNumber) summary.members().get("matchingClasses")).toLong();
10321032
final var differentApi = getDifferentApiCount(report);
1033-
final var missingUpstream = ((JsonNumber) summary.members().get("missingUpstream")).toNumber().longValue();
1033+
final var missingUpstream = ((JsonNumber) summary.members().get("missingUpstream")).toLong();
10341034

10351035
sb.append("## API Comparison Summary\n\n");
10361036
sb.append("| Metric | Count |\n");
@@ -1043,22 +1043,22 @@ static String generateSummary(JsonObject report) {
10431043
if (differentApi > 0) {
10441044
sb.append("## Changes Detected\n\n");
10451045

1046-
for (final var diff : differences.values()) {
1046+
for (final var diff : differences.elements()) {
10471047
final var diffObj = (JsonObject) diff;
1048-
final var status = ((JsonString) diffObj.members().get("status")).value();
1048+
final var status = ((JsonString) diffObj.members().get("status")).string();
10491049

10501050
if (!"DIFFERENT".equals(status)) continue;
10511051

1052-
final var className = ((JsonString) diffObj.members().get("className")).value();
1052+
final var className = ((JsonString) diffObj.members().get("className")).string();
10531053
sb.append("### ").append(className).append("\n\n");
10541054

10551055
final var classDiffs = (JsonArray) diffObj.members().get("differences");
10561056
if (classDiffs != null) {
1057-
for (final var change : classDiffs.values()) {
1057+
for (final var change : classDiffs.elements()) {
10581058
final var changeObj = (JsonObject) change;
1059-
final var type = ((JsonString) changeObj.members().get("type")).value();
1059+
final var type = ((JsonString) changeObj.members().get("type")).string();
10601060
final var methodValue = changeObj.members().get("method");
1061-
final var method = methodValue instanceof JsonString js ? js.value() : "unknown";
1061+
final var method = methodValue instanceof JsonString js ? js.string() : "unknown";
10621062

10631063
final var emoji = switch (type) {
10641064
case "methodRemoved" -> "➖";
@@ -1078,7 +1078,7 @@ static String generateSummary(JsonObject report) {
10781078
}
10791079

10801080
sb.append("---\n");
1081-
final var timestamp = ((JsonString) report.members().get("timestamp")).value();
1081+
final var timestamp = ((JsonString) report.members().get("timestamp")).string();
10821082
sb.append("*Generated by API Tracker on ").append(timestamp.split("T")[0]).append("*\n");
10831083

10841084
return sb.toString();
@@ -1090,4 +1090,4 @@ static String generateSummary(JsonObject report) {
10901090
static boolean hasDifferences(JsonObject report) {
10911091
return getDifferentApiCount(report) > 0;
10921092
}
1093-
}
1093+
}

0 commit comments

Comments
 (0)