Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed #589 (by adding skipObject() and skipArray() methods) #590

Merged
merged 4 commits into from
Mar 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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