Skip to content

Fix #571: Unable to deserialize a pojo with IonStruct #573

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

Merged
merged 4 commits into from
Apr 11, 2025

Conversation

seadbrane
Copy link
Contributor

@seadbrane seadbrane commented Apr 9, 2025

(fixes #571)

Make IonValueDeserializer a ContextualDeserializer in order to create the correct Ion null type.

Also, add new IonParser feature READ_NULL_AS_IONVALUE in order to be able to serialize null as either an IonNull or java null.

@cowtowncoder cowtowncoder added 2.19 cla-received Marker to denote that there is a CLA for pr labels Apr 10, 2025
@@ -563,6 +575,12 @@ private IonValue getIonValue() throws IOException {
writer.writeValue(_reader);
IonValue v = l.get(0);
v.removeFromContainer();

if (v.isNullValue() && !Feature.READ_NULL_AS_IONVALUE.enabledIn(_formatFeatures)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know existing is the way it is, but call above to:

_updateToken(JsonToken.VALUE_EMBEDDED_OBJECT);

looks wrong, given this is called (only) from getEmbeddedObject()... which should only be called when we do have JsonToken.VALUE_EMBEDDED_OBJECT (and if not, fail).

Would probably make sense to add a comment here to explain logic wrt !IonType.isContainer(v.getType()) -- I am not sure I understand the logic myself.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple of tests fail if this _updateToken(JsonToken.VALUE_EMBEDDED_OBJECT); is removed. Perhaps a 3.0 cleanup activity.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah. Makes sense there is a reason -- should have caught when these were added (or added comments to explain why/how)

class IonValueDeserializer extends JsonDeserializer<IonValue> {
class IonValueDeserializer extends JsonDeserializer<IonValue> implements ContextualDeserializer {

private final JavaType targetType;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Member variables with leading underscore -> _targetType

@@ -65,7 +73,7 @@ static class IonValueData extends Data<IonValue> {
}

private static final IonSystem SYSTEM = IonSystemBuilder.standard().build();
private static final IonValueMapper ION_VALUE_MAPPER = new IonValueMapper(SYSTEM, SNAKE_CASE);
private final IonValueMapper ION_VALUE_MAPPER = new IonValueMapper(SYSTEM, SNAKE_CASE);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why change from static to per-instance? Did it fail otherwise? (possibly due to null-value caching)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was changed so that it can be configured in each test, but not needed if I create a new IonValueMapper for the READ_NULL_AS_IONVALUE cases.

public void shouldBeAbleToDeserializeNullToIonNull() throws Exception {
String ion = "{c:null}";
verifyNullDeserialization(ion, SYSTEM.newNull());
ION_VALUE_MAPPER.disable(IonParser.Feature.READ_NULL_AS_IONVALUE);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should not try to change configuration of ION_VALUE_MAPPER after use, across methods; not guaranteed to take effect. Instead can create ObjectReader, call ObjectReader.with() and .without() to enable/disable features.

(also makes it easier to merge tests to 3.x as 3.x does not have methods to directly configure ObjectMapper)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should not try to change configuration of ION_VALUE_MAPPER after use,across methods; not guaranteed to take effect.

Why is that - caching?

Using ObjectReader is not a great option here, since it doesn't support Ion natively. Will create another IonValueMapper.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, indirectly caching of (de)serializers. Some of configuration settings affect construction and so effects remain if settings are changed.
Settings changed here are probably ok, although code won't work in 3.0 as mappers are truly immutable (builders only)

Copy link
Member

@cowtowncoder cowtowncoder left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks pretty good, couple of things to change.

@cowtowncoder cowtowncoder merged commit ad27eaa into FasterXML:2.19 Apr 11, 2025
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
2.19 cla-received Marker to denote that there is a CLA for pr
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Unable to deserialize a pojo with IonStruct
2 participants