From 507fae1a1d7d177431f09a7e936f14446affef5b Mon Sep 17 00:00:00 2001 From: rikkarth Date: Fri, 20 Sep 2024 16:15:56 +0100 Subject: [PATCH 1/4] JacksonCollectors.toJsonNode implementation --- .../databind/util/JacksonCollectors.java | 38 +++++++++++++++++++ .../databind/util/JacksonCollectorsTest.java | 33 ++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 src/main/java/com/fasterxml/jackson/databind/util/JacksonCollectors.java create mode 100644 src/test/java/com/fasterxml/jackson/databind/util/JacksonCollectorsTest.java diff --git a/src/main/java/com/fasterxml/jackson/databind/util/JacksonCollectors.java b/src/main/java/com/fasterxml/jackson/databind/util/JacksonCollectors.java new file mode 100644 index 0000000000..5939a77f1e --- /dev/null +++ b/src/main/java/com/fasterxml/jackson/databind/util/JacksonCollectors.java @@ -0,0 +1,38 @@ +package com.fasterxml.jackson.databind.util; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.JsonNodeCreator; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import java.util.stream.Collector; + +/** + * Utility class that provides custom {@link Collector} implementations to support Stream operations. + *

+ * This class is not meant to be instantiated and serves only as a utility class. + *

+ * + * @since 2.18 + */ +public abstract class JacksonCollectors { + /** + * Creates a {@link Collector} that collects {@link JsonNode} elements into an {@link ArrayNode}. + *

+ * This method uses a {@link JsonNodeFactory} to create an empty {@link ArrayNode} and then adds each + * {@link JsonNode} to it. + *

+ * + * @return a {@link Collector} that collects {@link JsonNode} elements into an {@link ArrayNode} + */ + public static Collector toJsonArray() { + return toJsonArray(JsonNodeFactory.instance); + } + + public static Collector toJsonArray(JsonNodeCreator nodeCreator) { + return Collector.of( + nodeCreator::arrayNode, // supplier + ArrayNode::add, // accumulator + ArrayNode::addAll // combiner + ); + } +} diff --git a/src/test/java/com/fasterxml/jackson/databind/util/JacksonCollectorsTest.java b/src/test/java/com/fasterxml/jackson/databind/util/JacksonCollectorsTest.java new file mode 100644 index 0000000000..d5705f4007 --- /dev/null +++ b/src/test/java/com/fasterxml/jackson/databind/util/JacksonCollectorsTest.java @@ -0,0 +1,33 @@ +package com.fasterxml.jackson.databind.util; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import java.util.stream.IntStream; +import org.junit.jupiter.api.Test; + +public class JacksonCollectorsTest { + + @Test + public void testToJsonArray() + { + final ObjectMapper objectMapper = new ObjectMapper(); + + final JsonNode jsonNodeResult = IntStream.range(0, 10) + .mapToObj(i -> { + ObjectNode objectNode = objectMapper.createObjectNode(); + objectNode.put("testString", "example"); + objectNode.put("testNumber", i); + objectNode.put("testBoolean", true); + + return objectNode; + }) + .collect(JacksonCollectors.toJsonArray()); + + assertEquals(10, jsonNodeResult.size()); + jsonNodeResult.forEach(jsonNode -> assertFalse(jsonNode.isEmpty())); + } +} From 006e43af0ab5b448b2810613b3cceb40b8f5558a Mon Sep 17 00:00:00 2001 From: rikkarth Date: Fri, 20 Sep 2024 18:54:38 +0100 Subject: [PATCH 2/4] signature rename to toArrayNode --- .../fasterxml/jackson/databind/util/JacksonCollectors.java | 6 +++--- .../jackson/databind/util/JacksonCollectorsTest.java | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/databind/util/JacksonCollectors.java b/src/main/java/com/fasterxml/jackson/databind/util/JacksonCollectors.java index 5939a77f1e..1f4cbc598b 100644 --- a/src/main/java/com/fasterxml/jackson/databind/util/JacksonCollectors.java +++ b/src/main/java/com/fasterxml/jackson/databind/util/JacksonCollectors.java @@ -24,11 +24,11 @@ public abstract class JacksonCollectors { * * @return a {@link Collector} that collects {@link JsonNode} elements into an {@link ArrayNode} */ - public static Collector toJsonArray() { - return toJsonArray(JsonNodeFactory.instance); + public static Collector toArrayNode() { + return toArrayNode(JsonNodeFactory.instance); } - public static Collector toJsonArray(JsonNodeCreator nodeCreator) { + public static Collector toArrayNode(JsonNodeCreator nodeCreator) { return Collector.of( nodeCreator::arrayNode, // supplier ArrayNode::add, // accumulator diff --git a/src/test/java/com/fasterxml/jackson/databind/util/JacksonCollectorsTest.java b/src/test/java/com/fasterxml/jackson/databind/util/JacksonCollectorsTest.java index d5705f4007..e589d045b1 100644 --- a/src/test/java/com/fasterxml/jackson/databind/util/JacksonCollectorsTest.java +++ b/src/test/java/com/fasterxml/jackson/databind/util/JacksonCollectorsTest.java @@ -12,7 +12,7 @@ public class JacksonCollectorsTest { @Test - public void testToJsonArray() + public void testToArrayNode() { final ObjectMapper objectMapper = new ObjectMapper(); @@ -25,7 +25,7 @@ public void testToJsonArray() return objectNode; }) - .collect(JacksonCollectors.toJsonArray()); + .collect(JacksonCollectors.toArrayNode()); assertEquals(10, jsonNodeResult.size()); jsonNodeResult.forEach(jsonNode -> assertFalse(jsonNode.isEmpty())); From c0d26db5615bb9c712f2aaf32b769687dcdbe7d7 Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Fri, 20 Sep 2024 14:12:27 -0700 Subject: [PATCH 3/4] Update release notes --- release-notes/CREDITS-2.x | 5 +++++ release-notes/VERSION-2.x | 2 ++ 2 files changed, 7 insertions(+) diff --git a/release-notes/CREDITS-2.x b/release-notes/CREDITS-2.x index 879cf86d0a..42dad748c5 100644 --- a/release-notes/CREDITS-2.x +++ b/release-notes/CREDITS-2.x @@ -1829,3 +1829,8 @@ Eduard Gomoliako (Gems@github) Mathijs Vogelzang (mathijs81@github) * Reported #4678: Java records don't serialize with `MapperFeature.REQUIRE_SETTERS_FOR_GETTERS` (2.18.0) + +Rikkarth (rikkarth@github) + * Contributed #4709: Add `JacksonCollectors` with `toArrayNode()` implementation + (2.18.0) + diff --git a/release-notes/VERSION-2.x b/release-notes/VERSION-2.x index 717bee8fde..228993d3c7 100644 --- a/release-notes/VERSION-2.x +++ b/release-notes/VERSION-2.x @@ -72,6 +72,8 @@ Project: jackson-databind (reported by Mathijs V) #4688: Should allow deserializing with no-arg `@JsonCreator(mode = DELEGATING)` (contributed by Carter K) +#4709: Add `JacksonCollectors` with `toArrayNode()` implementation + (contributed by @rikkarth) 2.17.2 (05-Jul-2024) From f777d1ab5c80030137c8efd8319bd399a38b3d65 Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Fri, 20 Sep 2024 14:16:11 -0700 Subject: [PATCH 4/4] Minor javadoc change --- .../databind/util/JacksonCollectors.java | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/fasterxml/jackson/databind/util/JacksonCollectors.java b/src/main/java/com/fasterxml/jackson/databind/util/JacksonCollectors.java index 1f4cbc598b..c6b47fc4e4 100644 --- a/src/main/java/com/fasterxml/jackson/databind/util/JacksonCollectors.java +++ b/src/main/java/com/fasterxml/jackson/databind/util/JacksonCollectors.java @@ -1,10 +1,11 @@ package com.fasterxml.jackson.databind.util; +import java.util.stream.Collector; + import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.JsonNodeCreator; import com.fasterxml.jackson.databind.node.JsonNodeFactory; -import java.util.stream.Collector; /** * Utility class that provides custom {@link Collector} implementations to support Stream operations. @@ -21,6 +22,9 @@ public abstract class JacksonCollectors { * This method uses a {@link JsonNodeFactory} to create an empty {@link ArrayNode} and then adds each * {@link JsonNode} to it. *

+ *

+ * Short-cut to + *{@code toArrayNode(JsonNodeFactory.instance}} * * @return a {@link Collector} that collects {@link JsonNode} elements into an {@link ArrayNode} */ @@ -28,6 +32,17 @@ public static Collector toArrayNode() { return toArrayNode(JsonNodeFactory.instance); } + /** + * Creates a {@link Collector} that collects {@link JsonNode} elements into an {@link ArrayNode}. + *

+ * This method uses a {@link JsonNodeFactory} to create an empty {@link ArrayNode} and then adds each + * {@link JsonNode} to it. + *

+ * + * @param nodeCreator Factory for constructing {@link ArrayNode} to contain nodes in + * + * @return a {@link Collector} that collects {@link JsonNode} elements into an {@link ArrayNode} + */ public static Collector toArrayNode(JsonNodeCreator nodeCreator) { return Collector.of( nodeCreator::arrayNode, // supplier