Skip to content

Allow disabling native type ids when deserializing for #270 #271

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 1 commit into from
Apr 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -291,15 +291,15 @@ public int getFormatGeneratorFeatures() {
* @since 2.7
*/
public IonParser createParser(IonReader in) {
return new IonParser(in, _system, _createContext(in, false), getCodec());
return new IonParser(in, _system, _createContext(in, false), getCodec(), _ionParserFeatures);
}

/**
* @since 2.7
*/
public IonParser createParser(IonValue value) {
IonReader in = value.getSystem().newReader(value);
return new IonParser(in, _system, _createContext(in, true), getCodec());
return new IonParser(in, _system, _createContext(in, true), getCodec(), _ionParserFeatures);
}

// NOTE! Suboptimal return type -- but can't change safely before 3.0 as return
Expand All @@ -324,7 +324,7 @@ public IonSystem getIonSystem() {
*/
@Deprecated
public IonParser createJsonParser(IonReader in) {
return new IonParser(in, _system, _createContext(in, false), getCodec());
return new IonParser(in, _system, _createContext(in, false), getCodec(), _ionParserFeatures);
}

/**
Expand All @@ -333,7 +333,7 @@ public IonParser createJsonParser(IonReader in) {
@Deprecated
public IonParser createJsonParser(IonValue value) {
IonReader in = value.getSystem().newReader(value);
return new IonParser(in, _system, _createContext(in, true), getCodec());
return new IonParser(in, _system, _createContext(in, true), getCodec(), _ionParserFeatures);
}

/**
Expand All @@ -355,14 +355,14 @@ protected JsonParser _createParser(InputStream in, IOContext ctxt)
throws IOException
{
IonReader ion = _system.newReader(in);
return new IonParser(ion, _system, ctxt, getCodec());
return new IonParser(ion, _system, ctxt, getCodec(), _ionParserFeatures);
}

@Override
protected JsonParser _createParser(Reader r, IOContext ctxt)
throws IOException
{
return new IonParser(_system.newReader(r), _system, ctxt, getCodec());
return new IonParser(_system.newReader(r), _system, ctxt, getCodec(), _ionParserFeatures);
}

@Override
Expand All @@ -376,7 +376,7 @@ protected JsonParser _createParser(char[] data, int offset, int len, IOContext c
protected JsonParser _createParser(byte[] data, int offset, int len, IOContext ctxt)
throws IOException
{
return new IonParser(_system.newReader(data, offset, len), _system, ctxt, getCodec());
return new IonParser(_system.newReader(data, offset, len), _system, ctxt, getCodec(), _ionParserFeatures);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,18 @@ public class IonParser
*/
public enum Feature implements FormatFeature // in 2.12
{
/**
* Whether to expect Ion native Type Id construct for indicating type (true);
* or "generic" type property (false) when deserializing.
*<p>
* Enabled by default for backwards compatibility as that has been the behavior
* of `jackson-dataformat-ion` since 2.9 (first official public version)
*
* @see <a href="https://amzn.github.io/ion-docs/docs/spec.html#annot">The Ion Specification</a>
*
* @since 2.12.3
*/
USE_NATIVE_TYPE_ID(true),
;

final boolean _defaultState;
Expand Down Expand Up @@ -113,6 +125,13 @@ private Feature(boolean defaultState) {
*/
protected JsonToken _valueToken;

/**
* Bit flag composed of bits that indicate which
* {@link IonParser.Feature}s
* are enabled.
*/
protected int _formatFeatures;

/*
/*****************************************************************
/* Construction
Expand All @@ -133,15 +152,16 @@ public IonParser(IonReader r, IOContext ctxt)
*/
@Deprecated
public IonParser(IonReader r, IOContext ctxt, ObjectCodec codec) {
this(r, IonSystemBuilder.standard().build(), ctxt, codec);
this(r, IonSystemBuilder.standard().build(), ctxt, codec, IonFactory.DEFAULT_ION_PARSER_FEATURE_FLAGS);
}

IonParser(IonReader r, IonSystem system, IOContext ctxt, ObjectCodec codec) {
Copy link
Member

Choose a reason for hiding this comment

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

We probably should retain this intermediate constructor (at least for 2.12.x); will add a deprecated variant after merge.

IonParser(IonReader r, IonSystem system, IOContext ctxt, ObjectCodec codec, int ionParserFeatures) {
this._reader = r;
this._ioContext = ctxt;
this._objectCodec = codec;
this._parsingContext = JsonReadContext.createRootContext(-1, -1, null);
this._system = system;
this._formatFeatures = ionParserFeatures;
}

@Override
Expand Down Expand Up @@ -179,7 +199,9 @@ public IonSystem getIonSystem() {

@Override
public boolean canReadTypeId() {
return true; // yes, Ion got 'em
// yes, Ion got 'em
// 31-Mar-2021, manaigrn: but we might want to ignore them as per [dataformats-binary#270]
return Feature.USE_NATIVE_TYPE_ID.enabledIn(_formatFeatures);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package com.fasterxml.jackson.dataformat.ion.polymorphism;

import java.io.IOException;

import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.dataformat.ion.IonObjectMapper;
import com.fasterxml.jackson.dataformat.ion.IonParser.Feature;
import org.junit.Assert;
import org.junit.Test;

import com.amazon.ion.IonValue;
import com.amazon.ion.system.IonSystemBuilder;

public class PolymorphicTypeAnnotationsTest {
private static final String SUBCLASS_TYPE_NAME = "subtype";

@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "base",
visible = true
)
@JsonSubTypes({
@Type(value = Subclass.class, name = SUBCLASS_TYPE_NAME),
})
static public class BaseClass {
}


public static class Subclass extends BaseClass {
public String base;
}


public static class Container {
public BaseClass objectWithType;
}


private static final IonValue CONTAINER_WITH_TYPED_OBJECT = asIonValue(
"{" +
" objectWithType:type::" +
" {" +
" base:\"" + SUBCLASS_TYPE_NAME + "\"," +
" }" +
"}");

@Test
public void testNativeTypeIdsDisabledReadsTypeAnnotationsSuccessfully() throws IOException {
IonObjectMapper mapper = new IonObjectMapper();
mapper.disable(Feature.USE_NATIVE_TYPE_ID);

Container containerWithBaseClass = mapper.readValue(CONTAINER_WITH_TYPED_OBJECT, Container.class);

Assert.assertTrue(containerWithBaseClass.objectWithType instanceof Subclass);
Assert.assertEquals(SUBCLASS_TYPE_NAME, ((Subclass) containerWithBaseClass.objectWithType).base);
}

private static IonValue asIonValue(final String ionStr) {
return IonSystemBuilder.standard()
.build()
.singleValue(ionStr);
}
}