This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git


The following commit(s) were added to refs/heads/master by this push:
     new 47d5de5  ISIS-2877: ro-vwr: make typed tuple rendering more compact
47d5de5 is described below

commit 47d5de54485a6f0cde978a47d17f5a6f2d210a19
Author: Andi Huber <[email protected]>
AuthorDate: Fri Feb 4 12:55:20 2022 +0100

    ISIS-2877: ro-vwr: make typed tuple rendering more compact
    
    - that is, configure the JSON generator to omit null properties
---
 .../isis/applib/util/schema/CommonDtoUtils.java    | 13 ++---
 .../applib/value/semantics/ValueDecomposition.java | 12 +++--
 commons/pom.xml                                    |  5 ++
 .../isis/commons/internal/resources/_Json.java     | 58 ++++++++++++++++------
 .../restclient/ActionParameterListBuilder.java     | 27 ++++------
 .../serialization/SerializationStrategy.java       | 34 +++++--------
 6 files changed, 85 insertions(+), 64 deletions(-)

diff --git 
a/api/applib/src/main/java/org/apache/isis/applib/util/schema/CommonDtoUtils.java
 
b/api/applib/src/main/java/org/apache/isis/applib/util/schema/CommonDtoUtils.java
index a3f89fc..cc81130 100644
--- 
a/api/applib/src/main/java/org/apache/isis/applib/util/schema/CommonDtoUtils.java
+++ 
b/api/applib/src/main/java/org/apache/isis/applib/util/schema/CommonDtoUtils.java
@@ -32,8 +32,6 @@ import java.util.Objects;
 import java.util.Optional;
 import java.util.function.Function;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
-
 import org.springframework.lang.Nullable;
 
 import org.apache.isis.applib.jaxb.JavaTimeXMLGregorianCalendarMarshalling;
@@ -58,6 +56,9 @@ import org.apache.isis.schema.common.v2.ValueDto;
 import org.apache.isis.schema.common.v2.ValueType;
 import org.apache.isis.schema.common.v2.ValueWithTypeDto;
 
+import static 
org.apache.isis.commons.internal.resources._Json.jaxbAnnotationSupport;
+import static 
org.apache.isis.commons.internal.resources._Json.onlyIncludeNonNull;
+
 import lombok.NonNull;
 import lombok.RequiredArgsConstructor;
 import lombok.SneakyThrows;
@@ -256,11 +257,11 @@ public final class CommonDtoUtils {
         }
     }
 
-    @SneakyThrows
     private String dtoToJson(final @Nullable Object dto) {
-        return dto!=null
-                ? new ObjectMapper().writer().writeValueAsString(dto)
-                : null;
+        return _Json.toString(
+                dto,
+                jaxbAnnotationSupport(),
+                onlyIncludeNonNull());
     }
 
     // -- VALUE RECORD
diff --git 
a/api/applib/src/main/java/org/apache/isis/applib/value/semantics/ValueDecomposition.java
 
b/api/applib/src/main/java/org/apache/isis/applib/value/semantics/ValueDecomposition.java
index a2a5ebb..f6fc311 100644
--- 
a/api/applib/src/main/java/org/apache/isis/applib/value/semantics/ValueDecomposition.java
+++ 
b/api/applib/src/main/java/org/apache/isis/applib/value/semantics/ValueDecomposition.java
@@ -25,6 +25,9 @@ import org.apache.isis.schema.common.v2.TypedTupleDto;
 import org.apache.isis.schema.common.v2.ValueType;
 import org.apache.isis.schema.common.v2.ValueWithTypeDto;
 
+import static 
org.apache.isis.commons.internal.resources._Json.jaxbAnnotationSupport;
+import static 
org.apache.isis.commons.internal.resources._Json.onlyIncludeNonNull;
+
 public final class ValueDecomposition extends _Either<ValueWithTypeDto, 
TypedTupleDto> {
     private static final long serialVersionUID = 1L;
 
@@ -43,10 +46,11 @@ public final class ValueDecomposition extends 
_Either<ValueWithTypeDto, TypedTup
     // used by RO-Viewer to render values
     public String toJson() {
         return this.<String>fold(
-                
fundamental->CommonDtoUtils.getFundamentalValueAsJson(fundamental),
-                composite->composite!=null
-                        ? _Json.toString(composite).presentElseFail()
-                        : null);
+                CommonDtoUtils::getFundamentalValueAsJson,
+                composite->_Json.toString(
+                        composite,
+                        jaxbAnnotationSupport(),
+                        onlyIncludeNonNull()));
     }
 
     // used by EncodableFacet
diff --git a/commons/pom.xml b/commons/pom.xml
index 62af205..d40995d 100644
--- a/commons/pom.xml
+++ b/commons/pom.xml
@@ -67,6 +67,11 @@
                        <groupId>com.fasterxml.jackson.core</groupId>
                        <artifactId>jackson-databind</artifactId>
                </dependency>
+               
+        <dependency>
+            <groupId>com.fasterxml.jackson.module</groupId>
+            <artifactId>jackson-module-jaxb-annotations</artifactId>
+        </dependency>
 
                <dependency>
                        <groupId>org.yaml</groupId>
diff --git 
a/commons/src/main/java/org/apache/isis/commons/internal/resources/_Json.java 
b/commons/src/main/java/org/apache/isis/commons/internal/resources/_Json.java
index efa8a3b..0bf7f40 100644
--- 
a/commons/src/main/java/org/apache/isis/commons/internal/resources/_Json.java
+++ 
b/commons/src/main/java/org/apache/isis/commons/internal/resources/_Json.java
@@ -22,15 +22,20 @@ import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.List;
+import java.util.function.UnaryOperator;
 
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
 import com.fasterxml.jackson.core.JsonParseException;
-import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.JsonMappingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule;
+
+import org.springframework.lang.Nullable;
 
 import org.apache.isis.commons.functional.Result;
 
+import lombok.SneakyThrows;
 import lombok.val;
 
 /**
@@ -51,7 +56,7 @@ public class _Json {
     private static <T> T _readJson(final Class<T> clazz, final InputStream 
content)
             throws JsonParseException, JsonMappingException, IOException {
 
-        return (T) new ObjectMapper().readValue(content, clazz);
+        return new ObjectMapper().readValue(content, clazz);
     }
 
     /**
@@ -90,7 +95,7 @@ public class _Json {
     private static <T> T _readJson(final Class<T> clazz, final String content)
             throws JsonParseException, JsonMappingException, IOException {
 
-        return (T) new ObjectMapper().readValue(content, clazz);
+        return new ObjectMapper().readValue(content, clazz);
     }
 
     /**
@@ -129,7 +134,7 @@ public class _Json {
     private static <T> T _readJson(final Class<T> clazz, final File content)
             throws JsonParseException, JsonMappingException, IOException {
 
-        return (T) new ObjectMapper().readValue(content, clazz);
+        return new ObjectMapper().readValue(content, clazz);
     }
 
     /**
@@ -143,7 +148,7 @@ public class _Json {
         return Result.of(()->_readJson(clazz, content));
     }
 
-    private static <T> List<T> _readJsonList(final Class<T> elementType, File 
content)
+    private static <T> List<T> _readJsonList(final Class<T> elementType, final 
File content)
             throws JsonParseException, JsonMappingException, IOException {
 
         val mapper = new ObjectMapper();
@@ -167,7 +172,7 @@ public class _Json {
     private static <T> T _readJson(final Class<T> clazz, final byte[] content)
             throws JsonParseException, JsonMappingException, IOException {
 
-        return (T) new ObjectMapper().readValue(content, clazz);
+        return new ObjectMapper().readValue(content, clazz);
     }
 
     /**
@@ -202,22 +207,43 @@ public class _Json {
 
     // -- WRITING
 
-    private static String _toString(ObjectMapper objectMapper, Object pojo) 
throws JsonProcessingException {
-        return objectMapper.writeValueAsString(pojo);
+    @FunctionalInterface
+    public static interface JsonCustomizer extends UnaryOperator<ObjectMapper> 
{};
+
+    /** enable indentation for the underlying generator */
+    public static JsonCustomizer indentedOutput() {
+        return mapper->mapper.enable(SerializationFeature.INDENT_OUTPUT);
+    }
+
+    /** only properties with non-null values are to be included */
+    public static JsonCustomizer onlyIncludeNonNull() {
+        return mapper->mapper.setSerializationInclusion(Include.NON_NULL);
     }
 
-    public static Result<String> toString(ObjectMapper objectMapper, Object 
pojo) {
-        return Result.of(()->_toString(objectMapper, pojo));
+    /** add support for JAXB annotations */
+    public static JsonCustomizer jaxbAnnotationSupport() {
+        return mapper->mapper.registerModule(new JaxbAnnotationModule());
     }
 
-    private static String _toString(Object pojo) throws 
JsonProcessingException {
-        val objectMapper = new ObjectMapper()
-                .enable(SerializationFeature.INDENT_OUTPUT);
-        return _toString(objectMapper, pojo);
+    /** when arrays or map, only non-null values are to be included */
+    public static JsonCustomizer onlyIncludeNonNullWhenNonScalar() {
+        return mapper->mapper
+                .disable(SerializationFeature.WRITE_NULL_MAP_VALUES) // 
doesn't seem to work...
+                .disable(SerializationFeature.WRITE_EMPTY_JSON_ARRAYS);
     }
 
-    public static Result<String> toString(Object pojo) {
-        return Result.of(()->_toString(pojo));
+    @SneakyThrows
+    public static String toString(
+            final @Nullable Object pojo,
+            final JsonCustomizer ... customizers) {
+        if(pojo==null) {
+            return null;
+        }
+        var mapper = new ObjectMapper();
+        for(JsonCustomizer customizer : customizers) {
+            mapper = customizer.apply(mapper);
+        }
+        return mapper.writeValueAsString(pojo);
     }
 
 }
diff --git 
a/mappings/restclient/applib/src/main/java/org/apache/isis/extensions/restclient/ActionParameterListBuilder.java
 
b/mappings/restclient/applib/src/main/java/org/apache/isis/extensions/restclient/ActionParameterListBuilder.java
index d02c72d..c0eb4b3 100644
--- 
a/mappings/restclient/applib/src/main/java/org/apache/isis/extensions/restclient/ActionParameterListBuilder.java
+++ 
b/mappings/restclient/applib/src/main/java/org/apache/isis/extensions/restclient/ActionParameterListBuilder.java
@@ -36,7 +36,7 @@ public class ActionParameterListBuilder {
     @Getter
     private final Map<String, Class<?>> actionParameterTypes = new 
LinkedHashMap<>();
 
-    public ActionParameterListBuilder addActionParameter(String parameterName, 
String parameterValue) {
+    public ActionParameterListBuilder addActionParameter(final String 
parameterName, final String parameterValue) {
         actionParameters.put(parameterName, parameterValue != null
                 ? value("\"" + parameterValue + "\"")
                         : value(JSON_NULL_LITERAL));
@@ -44,43 +44,43 @@ public class ActionParameterListBuilder {
         return this;
     }
 
-    public ActionParameterListBuilder addActionParameter(String parameterName, 
int parameterValue) {
+    public ActionParameterListBuilder addActionParameter(final String 
parameterName, final int parameterValue) {
         actionParameters.put(parameterName, value(""+parameterValue));
         actionParameterTypes.put(parameterName, int.class);
         return this;
     }
 
-    public ActionParameterListBuilder addActionParameter(String parameterName, 
long parameterValue) {
+    public ActionParameterListBuilder addActionParameter(final String 
parameterName, final long parameterValue) {
         actionParameters.put(parameterName, value(""+parameterValue));
         actionParameterTypes.put(parameterName, long.class);
         return this;
     }
 
-    public ActionParameterListBuilder addActionParameter(String parameterName, 
byte parameterValue) {
+    public ActionParameterListBuilder addActionParameter(final String 
parameterName, final byte parameterValue) {
         actionParameters.put(parameterName, value(""+parameterValue));
         actionParameterTypes.put(parameterName, byte.class);
         return this;
     }
 
-    public ActionParameterListBuilder addActionParameter(String parameterName, 
short parameterValue) {
+    public ActionParameterListBuilder addActionParameter(final String 
parameterName, final short parameterValue) {
         actionParameters.put(parameterName, value(""+parameterValue));
         actionParameterTypes.put(parameterName, short.class);
         return this;
     }
 
-    public ActionParameterListBuilder addActionParameter(String parameterName, 
double parameterValue) {
+    public ActionParameterListBuilder addActionParameter(final String 
parameterName, final double parameterValue) {
         actionParameters.put(parameterName, value(""+parameterValue));
         actionParameterTypes.put(parameterName, double.class);
         return this;
     }
 
-    public ActionParameterListBuilder addActionParameter(String parameterName, 
float parameterValue) {
+    public ActionParameterListBuilder addActionParameter(final String 
parameterName, final float parameterValue) {
         actionParameters.put(parameterName, value(""+parameterValue));
         actionParameterTypes.put(parameterName, float.class);
         return this;
     }
 
-    public ActionParameterListBuilder addActionParameter(String parameterName, 
boolean parameterValue) {
+    public ActionParameterListBuilder addActionParameter(final String 
parameterName, final boolean parameterValue) {
         actionParameters.put(parameterName, value(""+parameterValue));
         actionParameterTypes.put(parameterName, boolean.class);
         return this;
@@ -108,19 +108,12 @@ public class ActionParameterListBuilder {
 
     private static final String JSON_NULL_LITERAL = "null";
 
-    private String value(String valueLiteral) {
+    private String value(final String valueLiteral) {
         return "{\"value\" : " + valueLiteral + "}";
     }
 
-//    @SneakyThrows
-//    private String dto(Object dto) {
-//        val mapper = new ObjectMapper();
-//        return mapper.writeValueAsString(dto);
-//    }
-
-    private String toJson(Map.Entry<String, String> entry) {
+    private String toJson(final Map.Entry<String, String> entry) {
         return "   \""+entry.getKey()+"\": "+entry.getValue();
     }
 
-
 }
diff --git 
a/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/serialization/SerializationStrategy.java
 
b/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/serialization/SerializationStrategy.java
index fab7bbc..58d1cb5 100644
--- 
a/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/serialization/SerializationStrategy.java
+++ 
b/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/serialization/SerializationStrategy.java
@@ -22,13 +22,13 @@ import java.util.Collection;
 
 import javax.ws.rs.core.MediaType;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.SerializationFeature;
-import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule;
-
 import org.apache.isis.commons.internal.resources._Json;
 import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
 
+import static org.apache.isis.commons.internal.resources._Json.indentedOutput;
+import static 
org.apache.isis.commons.internal.resources._Json.jaxbAnnotationSupport;
+import static 
org.apache.isis.commons.internal.resources._Json.onlyIncludeNonNullWhenNonScalar;
+
 public enum SerializationStrategy {
 
     XML {
@@ -40,29 +40,21 @@ public enum SerializationStrategy {
 
     JSON {
         @Override public Object entity(final Object jaxbAnnotatedObject) {
-            final JaxbAnnotationModule jaxbAnnotationModule = new 
JaxbAnnotationModule();
-            final ObjectMapper objectMapper = new ObjectMapper()
-                    .registerModule(jaxbAnnotationModule)
-                    .disable(SerializationFeature.WRITE_NULL_MAP_VALUES) // 
doesn't seem to work...
-                    .disable(SerializationFeature.WRITE_EMPTY_JSON_ARRAYS);
-
-            return _Json.toString(objectMapper, jaxbAnnotatedObject)
-                    .presentElseFail();
+            return _Json.toString(
+                    jaxbAnnotatedObject,
+                    jaxbAnnotationSupport(),
+                    onlyIncludeNonNullWhenNonScalar());
         }
 
     },
 
     JSON_INDENTED {
         @Override public Object entity(final Object jaxbAnnotatedObject) {
-            final JaxbAnnotationModule jaxbAnnotationModule = new 
JaxbAnnotationModule();
-            final ObjectMapper objectMapper = new ObjectMapper()
-                    .registerModule(jaxbAnnotationModule)
-                    .enable(SerializationFeature.INDENT_OUTPUT)
-                    .disable(SerializationFeature.WRITE_NULL_MAP_VALUES) // 
doesn't seem to work...
-                    .disable(SerializationFeature.WRITE_EMPTY_JSON_ARRAYS);
-
-            return _Json.toString(objectMapper, jaxbAnnotatedObject)
-                    .presentElseFail();
+            return _Json.toString(
+                    jaxbAnnotatedObject,
+                    jaxbAnnotationSupport(),
+                    onlyIncludeNonNullWhenNonScalar(),
+                    indentedOutput());
         }
 
     },

Reply via email to