diff --git a/src/main/java/org/eclipse/yasson/internal/deserializer/types/JsonObjectDeserializer.java b/src/main/java/org/eclipse/yasson/internal/deserializer/types/JsonObjectDeserializer.java new file mode 100644 index 00000000..0bab9afe --- /dev/null +++ b/src/main/java/org/eclipse/yasson/internal/deserializer/types/JsonObjectDeserializer.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2025 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.internal.deserializer.types; + +import jakarta.json.JsonObject; +import jakarta.json.bind.JsonbException; +import jakarta.json.stream.JsonParser; + +import org.eclipse.yasson.internal.DeserializationContextImpl; +import org.eclipse.yasson.internal.deserializer.ModelDeserializer; +import org.eclipse.yasson.internal.properties.MessageKeys; +import org.eclipse.yasson.internal.properties.Messages; + +/** + * Deserializer of the {@link JsonObject} type. + */ +class JsonObjectDeserializer implements ModelDeserializer { + + private final ModelDeserializer delegate; + + JsonObjectDeserializer(TypeDeserializerBuilder builder) { + this.delegate = builder.getDelegate(); + } + + @Override + public Object deserialize(JsonParser value, DeserializationContextImpl context) { + JsonParser.Event last = context.getLastValueEvent(); + return delegate.deserialize(deserializeValue(last, value), context); + } + + private JsonObject deserializeValue(JsonParser.Event last, JsonParser parser) { + switch (last) { + case VALUE_NULL: + return null; + case START_OBJECT: + return parser.getObject(); + default: + throw new JsonbException(Messages.getMessage(MessageKeys.INVALID_DESERIALIZATION_JSON_TYPE, last)); + } + } +} diff --git a/src/main/java/org/eclipse/yasson/internal/deserializer/types/TypeDeserializers.java b/src/main/java/org/eclipse/yasson/internal/deserializer/types/TypeDeserializers.java index de1f7e00..0be594d6 100644 --- a/src/main/java/org/eclipse/yasson/internal/deserializer/types/TypeDeserializers.java +++ b/src/main/java/org/eclipse/yasson/internal/deserializer/types/TypeDeserializers.java @@ -47,6 +47,7 @@ import javax.xml.datatype.XMLGregorianCalendar; +import jakarta.json.JsonObject; import jakarta.json.JsonValue; import jakarta.json.bind.JsonbException; import jakarta.json.stream.JsonParser; @@ -173,6 +174,8 @@ public static ModelDeserializer getTypeDeserializer(Class clazz, if (JsonValue.class.equals(clazz)) { return new JsonValueDeserializer(builder, JsonValue.NULL); + } else if (JsonObject.class.equals(clazz)) { + return new JsonObjectDeserializer(builder); } else if (JsonValue.class.isAssignableFrom(clazz)) { return new JsonValueDeserializer(builder, null); } diff --git a/src/test/java/org/eclipse/yasson/defaultmapping/jsonp/JsonpTest.java b/src/test/java/org/eclipse/yasson/defaultmapping/jsonp/JsonpTest.java index 731c9f70..c8041c6a 100644 --- a/src/test/java/org/eclipse/yasson/defaultmapping/jsonp/JsonpTest.java +++ b/src/test/java/org/eclipse/yasson/defaultmapping/jsonp/JsonpTest.java @@ -13,6 +13,7 @@ package org.eclipse.yasson.defaultmapping.jsonp; import java.math.BigDecimal; +import java.util.List; import jakarta.json.Json; import jakarta.json.JsonArray; @@ -29,6 +30,7 @@ import org.eclipse.yasson.defaultmapping.jsonp.model.JsonpPojo; import org.junit.jupiter.api.Test; +import static org.eclipse.yasson.Assertions.shouldFail; import static org.eclipse.yasson.Jsonbs.defaultJsonb; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.nullValue; @@ -85,6 +87,16 @@ public void testInnerJsonObject() { } + @Test + public void testDeserializeNonObject() { + final JsonValue jsonString = Json.createValue("test"); + final JsonValue jsonNumber = Json.createValue(1); + for (JsonValue v : List.of(jsonString, jsonNumber, JsonValue.TRUE, JsonValue.EMPTY_JSON_ARRAY)) { + // Non-object JSON input should not be serialized into JsonObject + shouldFail(() -> defaultJsonb.fromJson(v.toString(), JsonObject.class)); + } + } + @Test public void testMarshallJsonArray() {