Skip to content

Commit b59886e

Browse files
committed
fix ReflectionUtils traversal issue that was failing for some Java types e.g. java.time.LocalDate
1 parent e85964c commit b59886e

4 files changed

Lines changed: 53 additions & 4 deletions

File tree

examples/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
</modules>
2020

2121
<properties>
22-
<jsonapi4j.version>1.8.3-SNAPSHOT</jsonapi4j.version>
22+
<jsonapi4j.version>1.8.3</jsonapi4j.version>
2323

2424
<jakarta.servlet-api.version>6.1.0</jakarta.servlet-api.version>
2525

jsonapi4j-base/src/main/java/pro/api4/jsonapi4j/util/ReflectionUtils.java

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,6 @@ private static void traverse(Class<?> clazz,
241241
}
242242
visited.add(clazz);
243243
for (Field field : clazz.getDeclaredFields()) {
244-
field.setAccessible(true);
245244
String path = prefix.isEmpty()
246245
? field.getName()
247246
: prefix + "." + field.getName();
@@ -260,7 +259,31 @@ private static boolean isLeafType(Class<?> clazz) {
260259
|| Boolean.class.equals(clazz)
261260
|| Character.class.equals(clazz)
262261
|| Date.class.isAssignableFrom(clazz)
263-
|| clazz.isEnum();
262+
|| clazz.isEnum()
263+
|| isJdkType(clazz);
264+
}
265+
266+
/**
267+
* Treats platform (JDK) types as opaque leaves so traversal never descends into them. JDK value
268+
* types such as {@code java.time.LocalDate}, {@code java.util.UUID} or {@code java.math.BigDecimal}
269+
* carry no domain-meaningful field paths, and the module system forbids making their internal
270+
* fields accessible (e.g. {@code java.base} does not open {@code java.time} to the unnamed module).
271+
*/
272+
private static boolean isJdkType(Class<?> clazz) {
273+
if (clazz.isArray()) {
274+
return false;
275+
}
276+
Package pkg = clazz.getPackage();
277+
if (pkg == null) {
278+
return false;
279+
}
280+
String name = pkg.getName();
281+
return name.startsWith("java.")
282+
|| name.startsWith("javax.")
283+
|| name.startsWith("jakarta.")
284+
|| name.startsWith("sun.")
285+
|| name.startsWith("com.sun.")
286+
|| name.startsWith("jdk.");
264287
}
265288

266289
/**

jsonapi4j-base/src/test/java/pro/api4/jsonapi4j/plugin/utils/ReflectionUtilsTests.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,24 @@ public void getAllFieldPaths_happyPath_checkResult() {
4343
);
4444
}
4545

46+
@Test
47+
public void getAllFieldPaths_jdkValueTypeAttributes_treatedAsLeavesAndNotTraversed() {
48+
// given - when
49+
Set<String> paths = ReflectionUtils.getAllFieldPaths(JdkTypes.class);
50+
51+
// then - JDK value types are leaf paths; traversal must not descend into their internals
52+
// (descending into e.g. java.time.LocalDate would throw InaccessibleObjectException)
53+
assertThat(paths).isEqualTo(
54+
Set.of(
55+
"localDate",
56+
"localDateTime",
57+
"instant",
58+
"uuid",
59+
"amount"
60+
)
61+
);
62+
}
63+
4664
@Test
4765
public void setFieldPathValueThrowing_nullObject_checkResult() {
4866
// given
@@ -226,6 +244,14 @@ public class Nested {
226244
Nested nested;
227245
}
228246

247+
public class JdkTypes {
248+
java.time.LocalDate localDate;
249+
java.time.LocalDateTime localDateTime;
250+
java.time.Instant instant;
251+
java.util.UUID uuid;
252+
java.math.BigDecimal amount;
253+
}
254+
229255
public class PathsTraversal {
230256
A a;
231257
String s;

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252

5353
<properties>
5454
<!--project revision-->
55-
<revision>1.8.3-SNAPSHOT</revision>
55+
<revision>1.8.3</revision>
5656

5757
<!--spting/web-->
5858
<spring.version>5.3.14</spring.version>

0 commit comments

Comments
 (0)