Skip to content

Commit

Permalink
Fixed #589 (by adding skipObject() and skipArray() methods) (#590)
Browse files Browse the repository at this point in the history
Fix issue #589 (implement skipObject() and skipArray() methods)
  • Loading branch information
greek1979 committed Mar 31, 2023
1 parent a5b6943 commit f3cbb35
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, 2022 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 2023 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 v. 2.0 which is available at
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2022 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2023 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 v. 2.0 which is available at
Expand All @@ -25,6 +25,9 @@
import jakarta.json.stream.JsonLocation;
import jakarta.json.stream.JsonParser;

import org.eclipse.yasson.internal.properties.MessageKeys;
import org.eclipse.yasson.internal.properties.Messages;

/**
* Adapter for {@link JsonParser}, that reads a {@link JsonStructure} content tree instead of JSON text.
*
Expand Down Expand Up @@ -66,9 +69,9 @@ public Event next() {
JsonStructureIterator current = iterators.peek();
Event next = current.next();
if (next == Event.START_OBJECT) {
iterators.push(new JsonObjectIterator((JsonObject) iterators.peek().getValue()));
iterators.push(new JsonObjectIterator((JsonObject) current.getValue()));
} else if (next == Event.START_ARRAY) {
iterators.push(new JsonArrayIterator((JsonArray) iterators.peek().getValue()));
iterators.push(new JsonArrayIterator((JsonArray) current.getValue()));
} else if (next == Event.END_OBJECT || next == Event.END_ARRAY) {
iterators.pop();
}
Expand Down Expand Up @@ -102,8 +105,14 @@ public BigDecimal getBigDecimal() {

@Override
public JsonObject getObject() {
// ((JsonObjectIterator) iterators.peek()).jsonObject
return iterators.peek().getValue().asJsonObject();
JsonStructureIterator current = iterators.peek();
if (current instanceof JsonObjectIterator) {
//Remove child iterator as getObject() method contract says
iterators.pop();
return current.getValue().asJsonObject();
} else {
throw new JsonbException(Messages.getMessage(MessageKeys.INTERNAL_ERROR, "Outside of object context"));
}
}

private JsonNumber getJsonNumberValue() {
Expand All @@ -120,6 +129,26 @@ public JsonLocation getLocation() {
throw new JsonbException("Operation not supported");
}

@Override
public void skipArray() {
if (!iterators.isEmpty()) {
JsonStructureIterator current = iterators.peek();
if (current instanceof JsonArrayIterator) {
iterators.pop();
}
}
}

@Override
public void skipObject() {
if (!iterators.isEmpty()) {
JsonStructureIterator current = iterators.peek();
if (current instanceof JsonObjectIterator) {
iterators.pop();
}
}
}

@Override
public void close() {
//noop
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2022 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2023 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 v. 2.0 which is available at
Expand Down Expand Up @@ -100,7 +100,7 @@ public void putAnnotation(Annotation annotation, boolean inherited, Class<?> def
// }
// annotations.put(annotation.annotationType(), new AnnotationWrapper(annotation, inherited));
annotations.computeIfAbsent(annotation.annotationType(), aClass -> new LinkedList<>())
.add(new AnnotationWrapper(annotation, inherited, definedType));
.add(new AnnotationWrapper<Annotation>(annotation, inherited, definedType));
}

public void putAnnotationWrapper(AnnotationWrapper<?> annotationWrapper) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/*
* Copyright (c) 2021, 2023 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 v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/

package org.eclipse.yasson.customization.polymorphism;

import jakarta.json.bind.annotation.JsonbSubtype;
import jakarta.json.bind.annotation.JsonbTypeInfo;

import org.eclipse.yasson.Jsonbs;
import org.junit.jupiter.api.Test;

import static org.eclipse.yasson.Jsonbs.defaultJsonb;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

/**
* Tests for verification of proper polymorphism handling based on annotation.
*/
public class NestedPolymorphismTest {

/**
* 1st test for: https://github.com/eclipse-ee4j/yasson/issues/589
* <p>(deserialization of nested polymorphic and unmapped properties)
*/
@Test
public void testNestedUnmappedProperty() {
String json = "{\"inner\":{\"id\":123,\"@type\":\"derivationA\","
+ "\"unmapped\":{\"x\":9,\"y\":[9,8,7]},\"name\":\"abc\"}}";
Outer obj = assertDoesNotThrow(() -> defaultJsonb.fromJson(json, Outer.class));
assertEquals(123L, obj.inner.id);
assertEquals("abc", obj.inner.name);
}

// a base class
@JsonbTypeInfo(key = "@type", value =
@JsonbSubtype(type = InnerBase.class, alias = "derivationA"))
public static class InnerBase {
public Long id;
public String name;
}

// derivation of the base class
public class Derivation extends InnerBase {}

// an arbitrary 'outer' root element
public static class Outer {
public InnerBase inner;
}

/**
* 2nd test for: https://github.com/eclipse-ee4j/yasson/issues/589
* <p>(deserialization of multiple nested polymorphic properties)
*/
@Test
public void testNestedDeserialization() {
String json = "{\"@type\":\"Pets\",\"pet1\":{\"@type\":\"Cat\",\"name\":\"kitty\"}"
+ ",\"pet2\":{\"@type\":\"Dog\",\"name\":\"puppy\"}}";
final Animals animals = Jsonbs.defaultJsonb.fromJson(json, Animals.class);
assertThat(animals, instanceOf(Pets.class));
assertNotNull(((Pets) animals).pet1, "Empty 'pet1' property");
assertEquals("kitty", ((Cat) ((Pets) animals).pet1).name, "First pet has invalid name");
assertNotNull(((Pets) animals).pet2, "Empty 'pet2' property");
assertThat("Invalid pet nr 2", ((Pets) animals).pet2, instanceOf(Dog.class));
}

@JsonbTypeInfo(key = "@type", value = {
@JsonbSubtype(alias = "Dog", type = Dog.class),
@JsonbSubtype(alias = "Cat", type = Cat.class)
})
public interface Pet {
public String getType();
}

public static class Dog implements Pet {

public String name;

@Override
public String getType() {
return "Dog";
}
}

public static class Cat implements Pet {

public String name;

@Override
public String getType() {
return "Cat";
}
}

@JsonbTypeInfo(key = "@type", value = {
@JsonbSubtype(alias = "Pets", type = Pets.class),
@JsonbSubtype(alias = "Fishes", type = Fishes.class)
})
public interface Animals {

}

public static class Pets implements Animals {
public Pet pet1;
public Pet pet2;
}

public static class Fishes implements Animals {

}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2020 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2023 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 v. 2.0 which is available at
Expand All @@ -22,9 +22,9 @@ public class ObjectDeserializerTest {

@Test
public void testGetInstanceExceptionShouldContainClassNameOnMissingConstructor() {
assertThrows(JsonbException.class,
() -> defaultJsonb.fromJson("{\"key\":\"value\"}", DummyDeserializationClass.class),
DummyDeserializationClass.class::getName);
assertThrows(JsonbException.class,
() -> defaultJsonb.fromJson("{\"key\":\"value\"}", DummyDeserializationClass.class),
DummyDeserializationClass.class::getName);
}

public static class DummyDeserializationClass {
Expand Down

0 comments on commit f3cbb35

Please sign in to comment.