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

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


The following commit(s) were added to refs/heads/master by this push:
     new 389b696  [JOHNZON-344] implicit object opening for serializer starting 
with writeStartArray(key)
389b696 is described below

commit 389b6964b2ac2e5f4d12007ae84296d0b911449d
Author: Romain Manni-Bucau <rmannibu...@gmail.com>
AuthorDate: Wed May 12 13:38:53 2021 +0200

    [JOHNZON-344] implicit object opening for serializer starting with 
writeStartArray(key)
---
 .../jsonb/api/experimental/JsonbExtensionTest.java | 90 +++++++++++++++++++++-
 .../johnzon/mapper/DynamicMappingGenerator.java    | 15 +++-
 2 files changed, 102 insertions(+), 3 deletions(-)

diff --git 
a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/api/experimental/JsonbExtensionTest.java
 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/api/experimental/JsonbExtensionTest.java
index a29b4ba..a2d612c 100644
--- 
a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/api/experimental/JsonbExtensionTest.java
+++ 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/api/experimental/JsonbExtensionTest.java
@@ -161,6 +161,33 @@ public class JsonbExtensionTest {
         assertEquals(attribs, deserialized);
     }
 
+    @Test
+    public void complexNoOpenCloseDeserializer() {
+        final LocalDate date = LocalDate.of(2021, Month.valueOf("MAY"), 12);
+        final LocalTime time = LocalTime.of(1, 2, 0, 0);
+        final OffsetDateTime offsetDateTime = OffsetDateTime.of(date, time, 
ZoneOffset.UTC);
+        final LocalDateTime localDateTime = LocalDateTime.of(date, time);
+
+        final Sink3 attribs = new Sink3();
+        attribs.attributes.put("ldateTime", new 
Wrapper3(singletonList(offsetDateTime)));
+        attribs.attributes.put("llocalDate", new 
Wrapper3(singletonList(date)));
+        attribs.attributes.put("llocalTime", new 
Wrapper3(singletonList(time)));
+        attribs.attributes.put("llocalDateTime", new 
Wrapper3(singletonList(localDateTime)));
+
+        final String json = jsonb.toJson(attribs);
+        assertJsonEquals("" +
+                        "{\"attributes\":{" +
+                        "\"ldateTime\":{\"value\":[\"2021-05-12T01:02Z\"]}" +
+                        ",\"llocalDate\":{\"value\":[\"2021-05-12\"]}" +
+                        
",\"llocalDateTime\":{\"value\":[\"2021-05-12T01:02\"]}" +
+                        ",\"llocalTime\":{\"value\":[\"01:02\"]}" +
+                        "}}",
+                json);
+
+        final Sink3 deserialized = jsonb.fromJson(json, Sink3.class);
+        assertEquals(attribs, deserialized);
+    }
+
     // assumes json are valid but enables nicer diff
     private void assertJsonEquals(final String expected, final String actual) {
         final JsonWriterFactory writerFactory = 
Json.createWriterFactory(singletonMap(JsonGenerator.PRETTY_PRINTING, true));
@@ -261,6 +288,57 @@ public class JsonbExtensionTest {
         }
     }
 
+    @JsonbTypeSerializer(OpenWrapperCodec.class)
+    @JsonbTypeDeserializer(OpenWrapperCodec.class)
+    public static class Wrapper3 extends Wrapper2 {
+        public Wrapper3() {
+            super();
+        }
+
+        public Wrapper3(final Object value) {
+            super(value);
+        }
+    }
+
+    public static class Sink3 implements Serializable {
+        private Map<String, Wrapper3> attributes = new TreeMap<>();
+
+        public Object get(final String name) {
+            final Wrapper3 att = attributes.get(name);
+            return att != null ? att.getValue() : null;
+        }
+
+        public void setAttributes(final Map<String, Wrapper3> attributes) {
+            this.attributes = attributes;
+        }
+
+        public Map<String, Wrapper3> getAttributes() {
+            return attributes;
+        }
+
+        @Override
+        public boolean equals(final Object obj) { // for test
+            return Sink3.class.isInstance(obj) && 
Objects.equals(Sink3.class.cast(obj).attributes, attributes);
+        }
+
+        @Override
+        public int hashCode() { // for test
+            return super.hashCode();
+        }
+    }
+
+    public static class OpenWrapperCodec extends WrapperCodec {
+        @Override
+        protected void afterList(final JsonGenerator generator) {
+            // no-op
+        }
+
+        @Override
+        protected void beforeList(final JsonGenerator generator) {
+            // no-op
+        }
+    }
+
     public static class WrapperCodec implements JsonbDeserializer<Wrapper2>, 
JsonbSerializer<Wrapper2> {
         @Override
         public void serialize(final Wrapper2 wrapper, final JsonGenerator 
generator, final SerializationContext ctx) {
@@ -271,9 +349,9 @@ public class JsonbExtensionTest {
             if (value instanceof List) {
                 final List<Object> list = (List<Object>) value;
                 if (!list.isEmpty()) {
-                    generator.writeStartObject();
+                    beforeList(generator);
                     writeArray(generator, list);
-                    generator.writeEnd();
+                    afterList(generator);
                 }
             } else if (value instanceof String) {
                 generator.write(markerFor(value), (String) value);
@@ -282,6 +360,14 @@ public class JsonbExtensionTest {
             }
         }
 
+        protected void afterList(final JsonGenerator generator) {
+            generator.writeEnd();
+        }
+
+        protected void beforeList(final JsonGenerator generator) {
+            generator.writeStartObject();
+        }
+
         private void writeArray(final JsonGenerator generator, final 
List<Object> list) {
             generator.writeStartArray("a" + markerFor(list.get(0)));
             for (final Object o : list) {
diff --git 
a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/DynamicMappingGenerator.java
 
b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/DynamicMappingGenerator.java
index ccf16c3..f5cb2ea 100644
--- 
a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/DynamicMappingGenerator.java
+++ 
b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/DynamicMappingGenerator.java
@@ -92,6 +92,7 @@ public class DynamicMappingGenerator implements 
MappingGenerator {
         private final String keyIfNoObject;
         private WritingState state = WritingState.NONE; // todo: we need a 
stack (linkedlist) here to be accurate
         private int nested = 0;
+        private boolean implicitStart;
 
         private InObjectOrPrimitiveJsonGenerator(final JsonGenerator 
generator, final Runnable writeStart,
                                                  final String keyName, final 
Runnable writeEnd) {
@@ -148,6 +149,10 @@ public class DynamicMappingGenerator implements 
MappingGenerator {
 
         @Override
         public JsonGenerator writeStartArray(final String name) {
+            if (state == WritingState.NONE && !implicitStart) { // force an 
enclosing object since we write in an object (we have a key)
+                writeStartObject();
+                implicitStart = true;
+            }
             if (state != WritingState.NONE) {
                 nested++;
             }
@@ -337,7 +342,11 @@ public class DynamicMappingGenerator implements 
MappingGenerator {
 
         @Override
         public JsonGenerator writeEnd() {
-            return doWriteEnd(false);
+            final JsonGenerator generator = doWriteEnd(false);
+            if (nested == 0 && implicitStart) {
+                doWriteEnd(false);
+            }
+            return generator;
         }
 
         private JsonGenerator doWriteEnd(final boolean useDelegate) {
@@ -562,6 +571,10 @@ public class DynamicMappingGenerator implements 
MappingGenerator {
         public JsonGenerator writeEnd() {
             if (level > 0) {
                 delegate.writeEnd();
+            } else if (level == 0 &&
+                    
InObjectOrPrimitiveJsonGenerator.class.isInstance(delegate) && // normally 
always true
+                    
InObjectOrPrimitiveJsonGenerator.class.cast(delegate).implicitStart) {
+                delegate.writeEnd();
             }
             level--;
             return this;

Reply via email to