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 <[email protected]>
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;