Fix UserDeserializer is called only once for an array of json objects… (#271)
diff --git a/src/main/java/org/eclipse/yasson/internal/serializer/DeserializerBuilder.java b/src/main/java/org/eclipse/yasson/internal/serializer/DeserializerBuilder.java index 8d83a38..6e939ce 100644 --- a/src/main/java/org/eclipse/yasson/internal/serializer/DeserializerBuilder.java +++ b/src/main/java/org/eclipse/yasson/internal/serializer/DeserializerBuilder.java
@@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2019 Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019 Payara Foundation and/or its affiliates. All rights reserved. * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 @@ -125,7 +125,7 @@ } //Third deserializer is a supported value type to deserialize to JSON_VALUE - if (isJsonValueEvent()) { + if (isJsonValueEvent(jsonEvent)) { final Optional<AbstractValueTypeDeserializer<?>> supportedTypeDeserializer = getSupportedTypeDeserializer(rawType); if (!supportedTypeDeserializer.isPresent()) { if (jsonEvent == JsonParser.Event.VALUE_NULL) { @@ -178,8 +178,14 @@ throw new JsonbException("unresolved type for deserialization: " + getRuntimeType()); } - private boolean isJsonValueEvent() { - switch (jsonEvent) { + /** + * Checks if event is a value event. + * + * @param event JSON event to check. + * @return True if one of value events. + */ + public static boolean isJsonValueEvent(JsonParser.Event event) { + switch (event) { case VALUE_NULL: case VALUE_FALSE: case VALUE_TRUE:
diff --git a/src/main/java/org/eclipse/yasson/internal/serializer/UserDeserializerDeserializer.java b/src/main/java/org/eclipse/yasson/internal/serializer/UserDeserializerDeserializer.java index e4968d1..000328b 100644 --- a/src/main/java/org/eclipse/yasson/internal/serializer/UserDeserializerDeserializer.java +++ b/src/main/java/org/eclipse/yasson/internal/serializer/UserDeserializerDeserializer.java
@@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016, 2018 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2019 Oracle and/or its affiliates. All rights reserved. * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. @@ -63,8 +63,9 @@ JsonParser.Event lastEvent = parserContext.getLastEvent(); final UserDeserializerParser userDeserializerParser = new UserDeserializerParser(parser); deserializerResult = (T) deserializerBinding.getJsonbDeserializer().deserialize(userDeserializerParser, context, getRuntimeType()); - //Avoid moving parser to the end of the object, if deserializer was for one value only. - if (lastEvent == JsonParser.Event.START_ARRAY || lastEvent == JsonParser.Event.START_OBJECT) { + //In case deserialized structure is json object or array and the parser is not advanced + //after enclosing bracket of deserialized object. + if (parser.getCurrentLevel() == parserContext && !DeserializerBuilder.isJsonValueEvent(lastEvent)) { userDeserializerParser.advanceParserToEnd(); } }
diff --git a/src/test/java/org/eclipse/yasson/serializers/SerializersTest.java b/src/test/java/org/eclipse/yasson/serializers/SerializersTest.java index eb1acd3..c5d9a55 100644 --- a/src/test/java/org/eclipse/yasson/serializers/SerializersTest.java +++ b/src/test/java/org/eclipse/yasson/serializers/SerializersTest.java
@@ -19,6 +19,7 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; +import java.lang.reflect.Type; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Calendar; @@ -28,11 +29,15 @@ import java.util.TimeZone; import java.util.TreeMap; +import javax.json.JsonObject; import javax.json.bind.Jsonb; import javax.json.bind.JsonbBuilder; import javax.json.bind.JsonbConfig; import javax.json.bind.JsonbException; import javax.json.bind.config.PropertyOrderStrategy; +import javax.json.bind.serializer.DeserializationContext; +import javax.json.bind.serializer.JsonbDeserializer; +import javax.json.stream.JsonParser; import org.eclipse.yasson.TestTypeToken; import org.eclipse.yasson.internal.model.ReverseTreeMap; @@ -447,6 +452,37 @@ assertEquals("{\"null\":\"value\"}", jsonb.toJson(singletonMap(null, "value"))); } + @Test + public void testDeserializeArrayWithAdvancingParserAfterObjectEnd() { + String json = "[{\"stringProperty\":\"Property 1 value\"},{\"stringProperty\":\"Property 2 value\"}]"; + Jsonb jsonb = JsonbBuilder.create(new JsonbConfig().withDeserializers(new SimplePojoDeserializer())); + SimplePojo[] result = jsonb.fromJson(json, SimplePojo[].class); + Assert.assertEquals(2, result.length); + } + + public class SimplePojoDeserializer implements JsonbDeserializer<SimplePojo> { + @Override + public SimplePojo deserialize(JsonParser parser, DeserializationContext ctx, Type rtType) { + //parser.getObject advances the parser to END_OBJECT. + JsonObject json = parser.getObject(); + SimplePojo simplePojo = new SimplePojo(); + simplePojo.setStringProperty(json.getString("stringProperty")); + return simplePojo; + } + } + + public class SimplePojo { + private String stringProperty; + + public String getStringProperty() { + return stringProperty; + } + + public void setStringProperty(String stringProperty) { + this.stringProperty = stringProperty; + } + } + private Box createPojoWithDates() { Date date = getExpectedDate(); Box box = createPojo();