Skip to content

Commit

Permalink
Allow disabling native type ids when deserializing for FasterXML#270
Browse files Browse the repository at this point in the history
  • Loading branch information
manaigrn-amzn committed Apr 1, 2021
1 parent 112ae75 commit 3c759c1
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 10 deletions.
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
*/
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) {
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
// but we might not want 'em
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);
}
}

0 comments on commit 3c759c1

Please sign in to comment.