This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch spring6
in repository https://gitbox.apache.org/repos/asf/causeway.git
The following commit(s) were added to refs/heads/spring6 by this push:
new a79274e017 CAUSEWAY-3684: [Commons] Json/YamlUtils support for Can<T>
a79274e017 is described below
commit a79274e01719582dd44e661a259a1ff3e76cc98f
Author: andi-huber <[email protected]>
AuthorDate: Sun Jan 28 15:42:40 2024 +0100
CAUSEWAY-3684: [Commons] Json/YamlUtils support for Can<T>
---
.../org/apache/causeway/commons/io/JsonUtils.java | 67 +++++++++++++++++++++-
.../org/apache/causeway/commons/io/YamlUtils.java | 2 +
.../apache/causeway/commons/io/JsonUtilsTest.java | 9 ++-
...lsTest.toStringUtf8_indentedOutput.approved.txt | 7 +++
.../apache/causeway/commons/io/YamlUtilsTest.java | 5 ++
.../io/YamlUtilsTest.toStringUtf8.approved.txt | 5 ++
.../apache/causeway/commons/io/_TestDomain.java | 4 ++
7 files changed, 96 insertions(+), 3 deletions(-)
diff --git
a/commons/src/main/java/org/apache/causeway/commons/io/JsonUtils.java
b/commons/src/main/java/org/apache/causeway/commons/io/JsonUtils.java
index b01e14223d..dd07eb9ec2 100644
--- a/commons/src/main/java/org/apache/causeway/commons/io/JsonUtils.java
+++ b/commons/src/main/java/org/apache/causeway/commons/io/JsonUtils.java
@@ -18,21 +18,34 @@
*/
package org.apache.causeway.commons.io;
+import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Optional;
import java.util.function.UnaryOperator;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.BeanProperty;
+import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import
com.fasterxml.jackson.module.jakarta.xmlbind.JakartaXmlBindAnnotationModule;
import org.springframework.lang.Nullable;
+import org.apache.causeway.commons.collections.Can;
import org.apache.causeway.commons.functional.Try;
+import org.apache.causeway.commons.internal.base._Casts;
import org.apache.causeway.commons.internal.context._Context;
import lombok.NonNull;
@@ -104,8 +117,8 @@ public class JsonUtils {
return source.tryReadAll((final InputStream is)->{
return Try.call(()->{
val mapper = createJacksonReader(customizers);
- val listFactory =
mapper.getTypeFactory().constructCollectionType(List.class, elementType);
- return mapper.readValue(is, listFactory);
+ val collectionType =
mapper.getTypeFactory().constructCollectionType(List.class, elementType);
+ return mapper.readValue(is, collectionType);
});
});
}
@@ -169,12 +182,61 @@ public class JsonUtils {
return mapper;
}
+ // -- CAN SUPPORT
+
+ static class CanDeserializer extends JsonDeserializer<Can<?>> implements
ContextualDeserializer {
+ private Class<?> elementType;
+ public CanDeserializer(final @NonNull Class<?> elementType) {
+ this.elementType = elementType;
+ }
+ @Override
+ public JsonDeserializer<?> createContextual(final
DeserializationContext ctxt, final BeanProperty beanProperty) throws
JsonMappingException {
+ var type = ctxt.getContextualType() != null
+ ? ctxt.getContextualType()
+ : beanProperty!=null
+ ? beanProperty.getMember().getType()
+ : null;
+ var elementType = type!=null && type.containedTypeCount()==1
+ ? type.containedType(0).getRawClass()
+ : Object.class;
+ return new CanDeserializer(elementType);
+ }
+ @Override
+ public Can<?> deserialize(
+ final JsonParser p, final DeserializationContext ctxt) throws
IOException {
+ val listType =
ctxt.getTypeFactory().constructCollectionType(List.class, elementType);
+ var list = ctxt.readValue(p, listType);
+ return Can.ofCollection(_Casts.uncheckedCast(list));
+ }
+ }
+ /** add support for reading Can<T> */
+ public ObjectMapper readingCanSupport(final ObjectMapper mapper) {
+ mapper.registerModule(new SimpleModule().addDeserializer(Can.class,
new CanDeserializer(Object.class)));
+ return mapper;
+ }
+
+ static class CanSerializer extends StdSerializer<Can<?>> {
+ private static final long serialVersionUID = 1L;
+ protected CanSerializer() { super(Can.class, false); }
+ @Override
+ public void serialize(final Can<?> value, final JsonGenerator gen,
+ final SerializerProvider provider) throws IOException {
+ gen.writeObject(value.toList());
+ }
+ }
+ /** add support for writing Can<T> */
+ public ObjectMapper writingCanSupport(final ObjectMapper mapper) {
+ mapper.registerModule(new SimpleModule().addSerializer(new
CanSerializer()));
+ return mapper;
+ }
+
// -- MAPPER FACTORY
private ObjectMapper createJacksonReader(
final JsonUtils.JacksonCustomizer ... customizers) {
var mapper = new ObjectMapper();
mapper = readingJavaTimeSupport(mapper);
+ mapper = readingCanSupport(mapper);
for(JsonUtils.JacksonCustomizer customizer : customizers) {
mapper = Optional.ofNullable(customizer.apply(mapper))
.orElse(mapper);
@@ -186,6 +248,7 @@ public class JsonUtils {
final JsonUtils.JacksonCustomizer ... customizers) {
var mapper = new ObjectMapper();
mapper = writingJavaTimeSupport(mapper);
+ mapper = writingCanSupport(mapper);
for(JsonUtils.JacksonCustomizer customizer : customizers) {
mapper = Optional.ofNullable(customizer.apply(mapper))
.orElse(mapper);
diff --git
a/commons/src/main/java/org/apache/causeway/commons/io/YamlUtils.java
b/commons/src/main/java/org/apache/causeway/commons/io/YamlUtils.java
index 4599b19ddd..a3c4a09c92 100644
--- a/commons/src/main/java/org/apache/causeway/commons/io/YamlUtils.java
+++ b/commons/src/main/java/org/apache/causeway/commons/io/YamlUtils.java
@@ -146,6 +146,7 @@ public class YamlUtils {
final JsonUtils.JacksonCustomizer ... customizers) {
var mapper = new ObjectMapper(new YAMLFactory());
mapper = JsonUtils.readingJavaTimeSupport(mapper);
+ mapper = JsonUtils.readingCanSupport(mapper);
for(JsonUtils.JacksonCustomizer customizer : customizers) {
mapper = Optional.ofNullable(customizer.apply(mapper))
.orElse(mapper);
@@ -161,6 +162,7 @@ public class YamlUtils {
var mapper = new ObjectMapper(new YAMLFactory()
.disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER));
mapper = JsonUtils.writingJavaTimeSupport(mapper);
+ mapper = JsonUtils.writingCanSupport(mapper);
for(JsonUtils.JacksonCustomizer customizer : customizers) {
mapper = Optional.ofNullable(customizer.apply(mapper))
.orElse(mapper);
diff --git
a/commons/src/test/java/org/apache/causeway/commons/io/JsonUtilsTest.java
b/commons/src/test/java/org/apache/causeway/commons/io/JsonUtilsTest.java
index 66c45e9784..28049048d6 100644
--- a/commons/src/test/java/org/apache/causeway/commons/io/JsonUtilsTest.java
+++ b/commons/src/test/java/org/apache/causeway/commons/io/JsonUtilsTest.java
@@ -60,7 +60,14 @@ class JsonUtilsTest {
"address": {
"zip":1234,
"street":"backerstreet"
- }
+ },
+ "additionalAddresses" : [ {
+ "zip" : 23,
+ "street" : "brownstreet"
+ }, {
+ "zip" : 34,
+ "street" : "bluestreet"
+ } ]
}
""";
diff --git
a/commons/src/test/java/org/apache/causeway/commons/io/JsonUtilsTest.toStringUtf8_indentedOutput.approved.txt
b/commons/src/test/java/org/apache/causeway/commons/io/JsonUtilsTest.toStringUtf8_indentedOutput.approved.txt
index f572fe9b5e..4514ff5d4a 100644
---
a/commons/src/test/java/org/apache/causeway/commons/io/JsonUtilsTest.toStringUtf8_indentedOutput.approved.txt
+++
b/commons/src/test/java/org/apache/causeway/commons/io/JsonUtilsTest.toStringUtf8_indentedOutput.approved.txt
@@ -4,6 +4,13 @@
"zip" : 1234,
"street" : "backerstreet"
},
+ "additionalAddresses" : [ {
+ "zip" : 23,
+ "street" : "brownstreet"
+ }, {
+ "zip" : 34,
+ "street" : "bluestreet"
+ } ],
"java8Time" : {
"localTime" : "17:33:45",
"localDate" : "2007-11-21",
diff --git
a/commons/src/test/java/org/apache/causeway/commons/io/YamlUtilsTest.java
b/commons/src/test/java/org/apache/causeway/commons/io/YamlUtilsTest.java
index 6e609d299b..66966a580e 100644
--- a/commons/src/test/java/org/apache/causeway/commons/io/YamlUtilsTest.java
+++ b/commons/src/test/java/org/apache/causeway/commons/io/YamlUtilsTest.java
@@ -48,6 +48,11 @@ class YamlUtilsTest {
var yamlTemplate = """
name: sven
address: {street: backerstreet, zip: 1234}
+ additionalAddresses:
+ - zip: 23
+ street: "brownstreet"
+ - zip: 34
+ street: "bluestreet"
java8Time:
localTime: ${localTime}
localDate: ${localDate}
diff --git
a/commons/src/test/java/org/apache/causeway/commons/io/YamlUtilsTest.toStringUtf8.approved.txt
b/commons/src/test/java/org/apache/causeway/commons/io/YamlUtilsTest.toStringUtf8.approved.txt
index db3bcc524a..db6037f6be 100644
---
a/commons/src/test/java/org/apache/causeway/commons/io/YamlUtilsTest.toStringUtf8.approved.txt
+++
b/commons/src/test/java/org/apache/causeway/commons/io/YamlUtilsTest.toStringUtf8.approved.txt
@@ -2,6 +2,11 @@ name: "sven"
address:
zip: 1234
street: "backerstreet"
+additionalAddresses:
+- zip: 23
+ street: "brownstreet"
+- zip: 34
+ street: "bluestreet"
java8Time:
localTime: "17:33:45"
localDate: "2007-11-21"
diff --git
a/commons/src/test/java/org/apache/causeway/commons/io/_TestDomain.java
b/commons/src/test/java/org/apache/causeway/commons/io/_TestDomain.java
index bf3fe7039a..43f2540354 100644
--- a/commons/src/test/java/org/apache/causeway/commons/io/_TestDomain.java
+++ b/commons/src/test/java/org/apache/causeway/commons/io/_TestDomain.java
@@ -30,6 +30,7 @@ import java.time.format.DateTimeFormatter;
import java.util.Map;
import java.util.Objects;
+import org.apache.causeway.commons.collections.Can;
import org.apache.causeway.commons.internal.base._StringInterpolation;
import lombok.experimental.UtilityClass;
@@ -40,6 +41,7 @@ class _TestDomain {
public static record Person(
String name,
Address address,
+ Can<Address> additionalAddresses,
Java8Time java8Time) {
}
@@ -88,6 +90,8 @@ class _TestDomain {
Person samplePerson() {
return new Person("sven", new Address(1234, "backerstreet"),
+ Can.of(new Address(23, "brownstreet"),
+ new Address(34, "bluestreet")),
new Java8Time(
LocalTime.of(17, 33, 45),
LocalDate.of(2007, 11, 21),