eclipse-ee4j / eclipse-ee4j/yasson

Deserializing Object or String

Open
#601 1 comment 0 reactions 0 assignees View on GitHub
bug
Dominant language
Java
Stars
218
Forks
109
Avg merge
1d 5h
Merged PRs (30d)
9

Description

When trying to deserialize a bean property which can be a String or an Object, there is no way to deserialize the object version.

**Version**
Yasson 3.0.3

**To Reproduce**

```
import jakarta.json.bind.JsonbBuilder;
import jakarta.json.bind.JsonbException;
import jakarta.json.bind.annotation.JsonbTypeDeserializer;
import jakarta.json.bind.serializer.DeserializationContext;
import jakarta.json.bind.serializer.JsonbDeserializer;
import jakarta.json.stream.JsonParser;
import java.lang.reflect.Type;

public class Test {

public static class Parent {

@JsonbTypeDeserializer(DomainDeserializer.class)
public Object domain;
}

public static class Child {
public String name;
}

public static class DomainDeserializer implements JsonbDeserializer {
@Override
public Object deserialize(JsonParser parser, DeserializationContext ctx, Type rtType) {
final JsonParser.Event event = parser.next();
if (event == JsonParser.Event.START_OBJECT) {
// Deserialize inner object
return ctx.deserialize(Child.class, parser);
} else if (event == JsonParser.Event.VALUE_STRING) {
return parser.getString();
} else {
throw new JsonbException("Unexpected json element " + event.name() + " " + parser.getString());
}
}
}

public static void main(String[] args) {

Parent parent1 = JsonbBuilder.create().fromJson("{\"domain\": \"test\"}", Parent.class);
Parent parent2 = JsonbBuilder.create().fromJson("{\"domain\": {\"name\":\"test\"}}", Parent.class);

}
}
```

**Additional context**

In the first case `Parent parent1 = JsonbBuilder.create().fromJson("{\"domain\": \"test\"}", Parent.class);`
We get :
```
Exception in thread "main" jakarta.json.bind.JsonbException: Internal error: There are no more elements available!
at org.eclipse.yasson.internal.DeserializationContextImpl.deserializeItem(DeserializationContextImpl.java:142)
at org.eclipse.yasson.internal.DeserializationContextImpl.deserialize(DeserializationContextImpl.java:127)
at org.eclipse.yasson.internal.JsonBinding.deserialize(JsonBinding.java:55)
at org.eclipse.yasson.internal.JsonBinding.fromJson(JsonBinding.java:62)
at org.apache.sis.internal.coveragejson.Test.main(Test.java:48)
Caused by: java.util.NoSuchElementException: There are no more elements available!
at org.eclipse.yasson.internal.deserializer.YassonParser.validate(YassonParser.java:192)
at org.eclipse.yasson.internal.deserializer.YassonParser.next(YassonParser.java:71)
at org.apache.sis.internal.coveragejson.Test$DomainDeserializer.deserialize(Test.java:34)
at org.eclipse.yasson.internal.deserializer.UserDefinedDeserializer.deserialize(UserDefinedDeserializer.java:69)
at org.eclipse.yasson.internal.deserializer.UserDefinedDeserializer.deserialize(UserDefinedDeserializer.java:26)
at org.eclipse.yasson.internal.deserializer.ObjectDeserializer.deserialize(ObjectDeserializer.java:78)
at org.eclipse.yasson.internal.deserializer.ObjectDeserializer.deserialize(ObjectDeserializer.java:31)
at org.eclipse.yasson.internal.deserializer.DefaultObjectInstanceCreator.deserialize(DefaultObjectInstanceCreator.java:57)
at org.eclipse.yasson.internal.deserializer.DefaultObjectInstanceCreator.deserialize(DefaultObjectInstanceCreator.java:29)
at org.eclipse.yasson.internal.deserializer.PositionChecker.deserialize(PositionChecker.java:85)
at org.eclipse.yasson.internal.deserializer.PositionChecker.deserialize(PositionChecker.java:34)
at org.eclipse.yasson.internal.deserializer.NullCheckDeserializer.deserialize(NullCheckDeserializer.java:46)
at org.eclipse.yasson.internal.deserializer.NullCheckDeserializer.deserialize(NullCheckDeserializer.java:26)
at org.eclipse.yasson.internal.DeserializationContextImpl.deserializeItem(DeserializationContextImpl.java:138)
... 4 more
```

In the second `Parent parent2 = JsonbBuilder.create().fromJson("{\"domain\": {\"name\":\"test\"}}", Parent.class);`
```
Exception in thread "main" jakarta.json.bind.JsonbException: Unable to deserialize property 'domain' because of: Unexpected json element KEY_NAME name
at org.eclipse.yasson.internal.deserializer.ObjectDeserializer.deserialize(ObjectDeserializer.java:80)
at org.eclipse.yasson.internal.deserializer.ObjectDeserializer.deserialize(ObjectDeserializer.java:31)
at org.eclipse.yasson.internal.deserializer.DefaultObjectInstanceCreator.deserialize(DefaultObjectInstanceCreator.java:57)
at org.eclipse.yasson.internal.deserializer.DefaultObjectInstanceCreator.deserialize(DefaultObjectInstanceCreator.java:29)
at org.eclipse.yasson.internal.deserializer.PositionChecker.deserialize(PositionChecker.java:85)
at org.eclipse.yasson.internal.deserializer.PositionChecker.deserialize(PositionChecker.java:34)
at org.eclipse.yasson.internal.deserializer.NullCheckDeserializer.deserialize(NullCheckDeserializer.java:46)
at org.eclipse.yasson.internal.deserializer.NullCheckDeserializer.deserialize(NullCheckDeserializer.java:26)
at org.eclipse.yasson.internal.DeserializationContextImpl.deserializeItem(DeserializationContextImpl.java:138)
at org.eclipse.yasson.internal.DeserializationContextImpl.deserialize(DeserializationContextImpl.java:127)
at org.eclipse.yasson.internal.JsonBinding.deserialize(JsonBinding.java:55)
at org.eclipse.yasson.internal.JsonBinding.fromJson(JsonBinding.java:62)
at org.apache.sis.internal.coveragejson.Test.main(Test.java:49)
Caused by: jakarta.json.bind.JsonbException: Unexpected json element KEY_NAME name
at org.apache.sis.internal.coveragejson.Test$DomainDeserializer.deserialize(Test.java:41)
at org.eclipse.yasson.internal.deserializer.UserDefinedDeserializer.deserialize(UserDefinedDeserializer.java:69)
at org.eclipse.yasson.internal.deserializer.UserDefinedDeserializer.deserialize(UserDefinedDeserializer.java:26)
at org.eclipse.yasson.internal.deserializer.ObjectDeserializer.deserialize(ObjectDeserializer.java:78)
... 12 more
```

**Expected behavior**
In the first case I would have expected a VALUE_STRING event but instead we have nothing.
In the second case I would have expected a START_OBJECT event but instead it jumps to the first attribute.

Or am I doing something wrong here ?

Contributor guide

Open the contributing guide

Research direction

Start by running the Java reproducer, then inspect DeserializationContextImpl.java and YassonParser.java using the stack traces as entry points. Add regression coverage for both string and object values and verify that custom deserializers receive the expected parser events without breaking existing deserialization behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.