yasson
yasson copied to clipboard
Deserializing Object or String
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<Object> {
@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 ?