From abdfade1eeb8f795e87314bb21657f5c1ad065ea Mon Sep 17 00:00:00 2001 From: Jan Bernitt Date: Mon, 18 May 2026 09:31:45 +0200 Subject: [PATCH] fix: always include collapsed properties in properties list --- .../org/hisp/dhis/jsontree/JsonObject.java | 13 ++-------- .../hisp/dhis/jsontree/JsonVirtualTree.java | 7 +----- .../hisp/dhis/jsontree/JsonValueToTest.java | 2 +- .../validation/JsonValidationRecordTest.java | 24 +++++++++++++++---- 4 files changed, 24 insertions(+), 22 deletions(-) diff --git a/src/main/java/org/hisp/dhis/jsontree/JsonObject.java b/src/main/java/org/hisp/dhis/jsontree/JsonObject.java index ae49a8d..865f8d2 100644 --- a/src/main/java/org/hisp/dhis/jsontree/JsonObject.java +++ b/src/main/java/org/hisp/dhis/jsontree/JsonObject.java @@ -88,23 +88,14 @@ record Property( * access is a property of the accessed {@link Property#jsonName()} with the same {@link * Property#javaName()}. * - * @return a model of this object in form its properties in no particular order + * @return a model of this object in form its properties in no particular order, including {@link + * Collapsed} properties for {@link Record}s * @since 1.4 */ static List properties(Class of) { return JsonVirtualTree.properties(of); } - /** - * @param of an object type - * @return a list of the properties in the given object type including those collapsed down from - * {@link Collapsed} inner {@link Record}s - * @since 1.9 - */ - static List collapsedProperties(Class of) { - return JsonVirtualTree.collapsedProperties(of); - } - /** * Access to object fields by name. * diff --git a/src/main/java/org/hisp/dhis/jsontree/JsonVirtualTree.java b/src/main/java/org/hisp/dhis/jsontree/JsonVirtualTree.java index a71afce..10ffd0a 100644 --- a/src/main/java/org/hisp/dhis/jsontree/JsonVirtualTree.java +++ b/src/main/java/org/hisp/dhis/jsontree/JsonVirtualTree.java @@ -79,7 +79,6 @@ final class JsonVirtualTree implements JsonMixed, Serializable { new JsonVirtualTree(JsonNode.NULL, JsonPath.SELF, JsonAccess.GLOBAL); private static final Map, List> PROPERTIES = new ConcurrentHashMap<>(); - private static final Map, List> COLLAPSED_PROPERTIES = new ConcurrentHashMap<>(); static List properties(Class of) { if (JsonObject.class.isAssignableFrom(of)) { @@ -90,16 +89,12 @@ static List properties(Class of) { if (Record.class.isAssignableFrom(of)) { @SuppressWarnings("unchecked") Class type = (Class) of; - return PROPERTIES.computeIfAbsent(type, t -> componentProperties(type)); + return PROPERTIES.computeIfAbsent(type, t -> collapsedComponentProperties(type)); } throw new UnsupportedOperationException( "Must be a subtype of JsonObject or Record but was: " + of); } - static List collapsedProperties(Class of) { - return COLLAPSED_PROPERTIES.computeIfAbsent(of, type -> collapsedComponentProperties(of)); - } - static JsonMixed lift(JsonNode node, JsonAccessors accessors) { return new JsonVirtualTree(node.getRoot(), node.path(), node, accessors); } diff --git a/src/test/java/org/hisp/dhis/jsontree/JsonValueToTest.java b/src/test/java/org/hisp/dhis/jsontree/JsonValueToTest.java index f7a9492..5971b6d 100644 --- a/src/test/java/org/hisp/dhis/jsontree/JsonValueToTest.java +++ b/src/test/java/org/hisp/dhis/jsontree/JsonValueToTest.java @@ -111,7 +111,7 @@ void testSingle() { } private static void assertParamsEquals(OuterParams expected, Map> actual) { - List properties = JsonObject.collapsedProperties(OuterParams.class); + List properties = JsonObject.properties(OuterParams.class); JsonNode object = JsonBuilder.createObject( obj -> { diff --git a/src/test/java/org/hisp/dhis/jsontree/validation/JsonValidationRecordTest.java b/src/test/java/org/hisp/dhis/jsontree/validation/JsonValidationRecordTest.java index 760807e..6ab5412 100644 --- a/src/test/java/org/hisp/dhis/jsontree/validation/JsonValidationRecordTest.java +++ b/src/test/java/org/hisp/dhis/jsontree/validation/JsonValidationRecordTest.java @@ -4,6 +4,8 @@ import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import java.util.function.Consumer; + +import org.hisp.dhis.jsontree.Collapsed; import org.hisp.dhis.jsontree.JsonMixed; import org.hisp.dhis.jsontree.Validation; import org.hisp.dhis.jsontree.Validator; @@ -18,7 +20,11 @@ class JsonValidationRecordTest { record SomeBean( - @Validation(minimum = 0) int age, @Validator(CustomValidator.class) String pattern) {} + @Validation(minimum = 0) int age, + @Validator(CustomValidator.class) String pattern, + @Collapsed InnerBean inner) {} + + record InnerBean(@Validation(minLength = 10, required = Validation.YesNo.NO) String name) {} record CustomValidator() implements Validation.Validator { @@ -32,7 +38,7 @@ public void validate(JsonMixed value, Consumer addError) { } @Test - void testMinimum_OK() { + void testRecord_Minimum_OK() { assertDoesNotThrow( () -> JsonMixed.of( @@ -42,12 +48,12 @@ void testMinimum_OK() { } @Test - void testMinimum_Required() { + void testRecord_Minimum_Required() { assertValidationError("{}", SomeBean.class, Validation.Rule.REQUIRED, "age"); } @Test - void testCustom_Validator() { + void testRecord_Custom_Validator() { assertValidationError( """ {"age": 10, "pattern": "bar"}""", @@ -55,4 +61,14 @@ void testCustom_Validator() { Validation.Rule.CUSTOM, "bar"); } + + @Test + void testRecord_CollapsedValidation() { + assertValidationError( + """ + {"age": 10, "pattern": "foo", "name": "tooShort"}""", + SomeBean.class, + Validation.Rule.MIN_LENGTH, + 10, 8); + } }