-
-
Notifications
You must be signed in to change notification settings - Fork 144
Description
Hello,
Following #295, we switched to 2.13 from 2.12 to be able to handle null.struct deserialization correctly but we bumped into a different problem in 2.13
We were trying to deserialize a test input into an entity with an optional IonValue field. We received IndexOutOfBoundsException when this property was missing in the input.
This is the stacktrace of the error:
at ExampleEntityTest.deserialization test without optional data(ExampleEntityTest.groovy:219)
Caused by: java.lang.IndexOutOfBoundsException: 0
at com.amazon.ion.impl.lite.IonContainerLite.get_child(IonContainerLite.java:663)
at com.amazon.ion.impl.lite.IonContainerLite.get(IonContainerLite.java:151)
at com.fasterxml.jackson.dataformat.ion.IonParser.getIonValue(IonParser.java:424)
at com.fasterxml.jackson.dataformat.ion.IonParser.getEmbeddedObject(IonParser.java:442)
at com.fasterxml.jackson.dataformat.ion.ionvalue.IonValueDeserializer.getNullValue(IonValueDeserializer.java:61)
at com.fasterxml.jackson.dataformat.ion.ionvalue.IonValueDeserializer.getNullValue(IonValueDeserializer.java:32)
at com.fasterxml.jackson.databind.JsonDeserializer.getAbsentValue(JsonDeserializer.java:350)
at com.fasterxml.jackson.databind.deser.impl.PropertyValueBuffer._findMissing(PropertyValueBuffer.java:203)
at com.fasterxml.jackson.databind.deser.impl.PropertyValueBuffer.getParameters(PropertyValueBuffer.java:158)
at com.fasterxml.jackson.databind.deser.ValueInstantiator.createFromObjectWith(ValueInstantiator.java:288)
at com.fasterxml.jackson.databind.deser.impl.PropertyBasedCreator.build(PropertyBasedCreator.java:202)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:518)
The problem occurs when IonValueDeserializer tries to execute the overridden getNullValue for the missing property. In the beginning of this method it tries to get the embedded object from IonParser.
@Override
public IonValue getNullValue(DeserializationContext ctxt) throws JsonMappingException {
try {
Object embeddedObj = ctxt.getParser().getEmbeddedObject();
...
}
IonParser's getEmbeddedObject method basically checks the token first but since in our case _currToken is END_OBJECT for the missing property so it skips the whole method and fallback to getIonValue().
Now in getIonValue _currToken is assigned to JsonToken.VALUE_EMBEDDED_OBJECT directly and it tries to write reader into an IonList. But since there is nothing to read for a missing property no IonValue is written into IonList.
And since there is no size check, in the next line when it tries to access the first value in the list we get an java.lang.IndexOutOfBoundsException
@SuppressWarnings("resource")
private IonValue getIonValue() throws IOException {
if (_system == null) {
throw new IllegalStateException("This "+getClass().getSimpleName()+" instance cannot be used for IonValue mapping");
}
_currToken = JsonToken.VALUE_EMBEDDED_OBJECT;
IonList l = _system.newEmptyList();
IonWriter writer = _system.newWriter(l);
writer.writeValue(_reader);
IonValue v = l.get(0);
v.removeFromContainer();
return v;
}
@Override
public Object getEmbeddedObject() throws IOException {
if (_currToken == JsonToken.VALUE_EMBEDDED_OBJECT) {
switch (_reader.getType()) {
case TIMESTAMP:
return _reader.timestampValue();
case BLOB:
case CLOB:
return _reader.newBytes();
// What about CLOB?
default:
}
}
return getIonValue();
}
Can someone confirm if this is a bug or not?