From e7a560a4622f7292fd91258a59ad3b55621cf79a Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Wed, 22 Oct 2025 17:32:17 -0700 Subject: [PATCH 1/4] Fix #619: add mapper.isEnabled(FormatRead/WriteFeature) methods --- .../jackson/dataformat/avro/AvroMapper.java | 14 ++++++++ .../dataformat/avro/MapperConfigTest.java | 33 ++++++++++++------- release-notes/CREDITS | 5 +++ release-notes/VERSION | 6 ++++ 4 files changed, 47 insertions(+), 11 deletions(-) diff --git a/avro/src/main/java/tools/jackson/dataformat/avro/AvroMapper.java b/avro/src/main/java/tools/jackson/dataformat/avro/AvroMapper.java index 337ab12b9..1c7d56830 100644 --- a/avro/src/main/java/tools/jackson/dataformat/avro/AvroMapper.java +++ b/avro/src/main/java/tools/jackson/dataformat/avro/AvroMapper.java @@ -205,6 +205,20 @@ public AvroFactory tokenStreamFactory() { return (AvroFactory) _streamFactory; } + /* + /********************************************************** + /* Format-specific + /********************************************************** + */ + + public boolean isEnabled(AvroReadFeature f) { + return _deserializationConfig.hasFormatFeature(f); + } + + public boolean isEnabled(AvroWriteFeature f) { + return _serializationConfig.hasFormatFeature(f); + } + /* /********************************************************************** /* Schema introspection diff --git a/avro/src/test/java/tools/jackson/dataformat/avro/MapperConfigTest.java b/avro/src/test/java/tools/jackson/dataformat/avro/MapperConfigTest.java index 3b5f22658..93f9de869 100644 --- a/avro/src/test/java/tools/jackson/dataformat/avro/MapperConfigTest.java +++ b/avro/src/test/java/tools/jackson/dataformat/avro/MapperConfigTest.java @@ -2,6 +2,8 @@ import java.io.ByteArrayOutputStream; +import org.junit.jupiter.api.Test; + import tools.jackson.core.FormatSchema; import tools.jackson.core.StreamReadCapability; import tools.jackson.core.StreamWriteFeature; @@ -28,6 +30,7 @@ public String getSchemaType() { /********************************************************************** */ + @Test public void testFactoryDefaults() throws Exception { assertTrue(MAPPER.tokenStreamFactory().isEnabled(AvroReadFeature.AVRO_BUFFERING)); @@ -38,25 +41,29 @@ public void testFactoryDefaults() throws Exception assertFalse(MAPPER.tokenStreamFactory().canUseSchema(BOGUS_SCHEMA)); } + @Test public void testParserDefaults() throws Exception { - AvroParser p = (AvroParser) MAPPER.createParser(new byte[0]); - assertTrue(p.isEnabled(AvroReadFeature.AVRO_BUFFERING)); - p.close(); + try (AvroParser p = (AvroParser) MAPPER.createParser(new byte[0])) { + assertTrue(p.isEnabled(AvroReadFeature.AVRO_BUFFERING)); + } AvroMapper mapper = AvroMapper.builder() .disable(AvroReadFeature.AVRO_BUFFERING) .build(); - p = (AvroParser) mapper.createParser(new byte[0]); - assertFalse(p.isEnabled(AvroReadFeature.AVRO_BUFFERING)); - - // 15-Jan-2021, tatu: 2.14 added this setting, not enabled in - // default set - assertTrue(p.streamReadCapabilities().isEnabled(StreamReadCapability.EXACT_FLOATS)); + try (AvroParser p = (AvroParser) mapper.createParser(new byte[0])) { + assertFalse(p.isEnabled(AvroReadFeature.AVRO_BUFFERING)); + + // 15-Jan-2021, tatu: 2.14 added this setting, not enabled in + // default set + assertTrue(p.streamReadCapabilities().isEnabled(StreamReadCapability.EXACT_FLOATS)); + } - p.close(); - } + // [dataformats-binary#619] + assertTrue(MAPPER.isEnabled(AvroReadFeature.AVRO_BUFFERING)); +} + @Test public void testGeneratorDefaults() throws Exception { ByteArrayOutputStream bytes = new ByteArrayOutputStream(); @@ -76,6 +83,9 @@ public void testGeneratorDefaults() throws Exception .createGenerator(bytes); assertFalse(g.isEnabled(AvroWriteFeature.AVRO_BUFFERING)); g.close(); + + // [dataformats-binary#619] + assertFalse(MAPPER.isEnabled(AvroWriteFeature.AVRO_FILE_OUTPUT)); } /* @@ -84,6 +94,7 @@ public void testGeneratorDefaults() throws Exception /********************************************************************** */ + @Test public void testDefaultSettingsWithAvroMapper() { AvroMapper mapper = new AvroMapper(); diff --git a/release-notes/CREDITS b/release-notes/CREDITS index 27f14275c..67f409da2 100644 --- a/release-notes/CREDITS +++ b/release-notes/CREDITS @@ -18,3 +18,8 @@ Fawzi Essam (@iifawzi) * Contribited #591: Change `CBOR` Features defaults for 3.0 (3.0.0) +Andy Wilkinson (@wilkinsona) + +* Requested #619: (avro, cbor) Add `isEnabled()` methods for format-specific features (like + `CBORReadFeature` and `CBORWriteFeature`) to mappers + (3.1.0) diff --git a/release-notes/VERSION b/release-notes/VERSION index 35dc1b424..3b81bc7ff 100644 --- a/release-notes/VERSION +++ b/release-notes/VERSION @@ -14,6 +14,12 @@ implementations) === Releases === ------------------------------------------------------------------------ +3.1.0 (not yet released) + +#619: (avro, cbor) Add `isEnabled()` methods for format-specific features (like + `CBORReadFeature` and `CBORWriteFeature`) to mappers + (requested by Andy W) + 3.0.1 (21-Oct-2025) No changes since 3.0.0 From 80cf80d85fa63bae1eafdf722694124734cd0a3a Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Wed, 22 Oct 2025 17:39:51 -0700 Subject: [PATCH 2/4] Add to CBOR --- .../tools/jackson/dataformat/cbor/CBORMapper.java | 14 ++++++++++++++ .../jackson/dataformat/cbor/CBORWriteFeature.java | 3 +++ .../dataformat/cbor/mapper/CBORMapperTest.java | 8 ++++++++ 3 files changed, 25 insertions(+) diff --git a/cbor/src/main/java/tools/jackson/dataformat/cbor/CBORMapper.java b/cbor/src/main/java/tools/jackson/dataformat/cbor/CBORMapper.java index 7a4078462..59ef818b0 100644 --- a/cbor/src/main/java/tools/jackson/dataformat/cbor/CBORMapper.java +++ b/cbor/src/main/java/tools/jackson/dataformat/cbor/CBORMapper.java @@ -173,6 +173,20 @@ public CBORFactory tokenStreamFactory() { return (CBORFactory) _streamFactory; } + /* + /********************************************************************** + /* Format-specific + /********************************************************************** + */ + + public boolean isEnabled(CBORReadFeature f) { + return _deserializationConfig.hasFormatFeature(f); + } + + public boolean isEnabled(CBORWriteFeature f) { + return _serializationConfig.hasFormatFeature(f); + } + /* /********************************************************** /* Helper class(es) diff --git a/cbor/src/main/java/tools/jackson/dataformat/cbor/CBORWriteFeature.java b/cbor/src/main/java/tools/jackson/dataformat/cbor/CBORWriteFeature.java index fd7319973..af88ee3ca 100644 --- a/cbor/src/main/java/tools/jackson/dataformat/cbor/CBORWriteFeature.java +++ b/cbor/src/main/java/tools/jackson/dataformat/cbor/CBORWriteFeature.java @@ -15,6 +15,9 @@ public enum CBORWriteFeature implements FormatFeature * representation that is enough to retain value; if false, will use * length indicated by argument type (4-byte for int, * 8-byte for long and so on). + *

+ * Default value is {@code true} meaning that minimal representation is used + * when encoding. */ WRITE_MINIMAL_INTS(true), diff --git a/cbor/src/test/java/tools/jackson/dataformat/cbor/mapper/CBORMapperTest.java b/cbor/src/test/java/tools/jackson/dataformat/cbor/mapper/CBORMapperTest.java index e67073aef..90aa096ee 100644 --- a/cbor/src/test/java/tools/jackson/dataformat/cbor/mapper/CBORMapperTest.java +++ b/cbor/src/test/java/tools/jackson/dataformat/cbor/mapper/CBORMapperTest.java @@ -151,4 +151,12 @@ public void testNegativeBigIntegerWithoutLeadingZero() throws Exception { assertEquals(BigInteger.ONE, mapper2.readValue(encodedNegative, BigInteger.class)); } + + // [dataformats-binary#619] + @Test + void testFormatFeatureDefaults() { + CBORMapper mapper = CBORMapper.shared(); + assertTrue(mapper.isEnabled(CBORReadFeature.DECODE_USING_STANDARD_NEGATIVE_BIGINT_ENCODING)); + assertTrue(mapper.isEnabled(CBORWriteFeature.WRITE_MINIMAL_INTS)); + } } From 2848abded30a6fc75fa8d58aeae76d8080a343a6 Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Wed, 22 Oct 2025 17:44:33 -0700 Subject: [PATCH 3/4] Add Ion --- .../jackson/dataformat/avro/AvroMapper.java | 4 ++-- .../jackson/dataformat/cbor/CBORMapper.java | 4 ++-- .../dataformat/ion/IonObjectMapper.java | 16 ++++++++++++++++ .../ion/misc/FeatureDefaultsTest.java | 18 ++++++++++++++++++ release-notes/VERSION | 2 +- 5 files changed, 39 insertions(+), 5 deletions(-) create mode 100644 ion/src/test/java/tools/jackson/dataformat/ion/misc/FeatureDefaultsTest.java diff --git a/avro/src/main/java/tools/jackson/dataformat/avro/AvroMapper.java b/avro/src/main/java/tools/jackson/dataformat/avro/AvroMapper.java index 1c7d56830..e23ca2636 100644 --- a/avro/src/main/java/tools/jackson/dataformat/avro/AvroMapper.java +++ b/avro/src/main/java/tools/jackson/dataformat/avro/AvroMapper.java @@ -206,9 +206,9 @@ public AvroFactory tokenStreamFactory() { } /* - /********************************************************** + /********************************************************************** /* Format-specific - /********************************************************** + /********************************************************************** */ public boolean isEnabled(AvroReadFeature f) { diff --git a/cbor/src/main/java/tools/jackson/dataformat/cbor/CBORMapper.java b/cbor/src/main/java/tools/jackson/dataformat/cbor/CBORMapper.java index 59ef818b0..4ed81c134 100644 --- a/cbor/src/main/java/tools/jackson/dataformat/cbor/CBORMapper.java +++ b/cbor/src/main/java/tools/jackson/dataformat/cbor/CBORMapper.java @@ -110,9 +110,9 @@ protected Object readResolve() { } /* - /********************************************************** + /********************************************************************** /* Life-cycle - /********************************************************** + /********************************************************************** */ public CBORMapper() { diff --git a/ion/src/main/java/tools/jackson/dataformat/ion/IonObjectMapper.java b/ion/src/main/java/tools/jackson/dataformat/ion/IonObjectMapper.java index 47992e4e1..29f48f872 100644 --- a/ion/src/main/java/tools/jackson/dataformat/ion/IonObjectMapper.java +++ b/ion/src/main/java/tools/jackson/dataformat/ion/IonObjectMapper.java @@ -27,6 +27,7 @@ import tools.jackson.databind.deser.DeserializationContextExt; import tools.jackson.databind.module.SimpleModule; import tools.jackson.databind.ser.SerializationContextExt; + import tools.jackson.dataformat.ion.ionvalue.IonValueModule; import com.amazon.ion.IonDatagram; @@ -276,6 +277,21 @@ public IonFactory tokenStreamFactory() { return (IonFactory) _streamFactory; } + /* + /********************************************************************** + /* Format-specific + /********************************************************************** + */ + + public boolean isEnabled(IonReadFeature f) { + return _deserializationConfig.hasFormatFeature(f); + } + + public boolean isEnabled(IonWriteFeature f) { + return _serializationConfig.hasFormatFeature(f); + } + + /* /************************************************************************ /* Additional convenience factory methods for parsers, generators diff --git a/ion/src/test/java/tools/jackson/dataformat/ion/misc/FeatureDefaultsTest.java b/ion/src/test/java/tools/jackson/dataformat/ion/misc/FeatureDefaultsTest.java new file mode 100644 index 000000000..01e5fd597 --- /dev/null +++ b/ion/src/test/java/tools/jackson/dataformat/ion/misc/FeatureDefaultsTest.java @@ -0,0 +1,18 @@ +package tools.jackson.dataformat.ion.misc; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; + +import tools.jackson.dataformat.ion.*; + +public class FeatureDefaultsTest +{ + // [dataformats-binary#619] + @Test + void testFormatFeatureDefaults() { + IonObjectMapper mapper = IonObjectMapper.shared(); + assertTrue(mapper.isEnabled(IonReadFeature.USE_NATIVE_TYPE_ID)); + assertTrue(mapper.isEnabled(IonWriteFeature.USE_NATIVE_TYPE_ID)); + } +} diff --git a/release-notes/VERSION b/release-notes/VERSION index 3b81bc7ff..18dbbb187 100644 --- a/release-notes/VERSION +++ b/release-notes/VERSION @@ -16,7 +16,7 @@ implementations) 3.1.0 (not yet released) -#619: (avro, cbor) Add `isEnabled()` methods for format-specific features (like +#619: (avro, cbor, ion) Add `isEnabled()` methods for format-specific features (like `CBORReadFeature` and `CBORWriteFeature`) to mappers (requested by Andy W) From ecbc0436a3b601897196e4ff1d818fcf426c425d Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Wed, 22 Oct 2025 17:50:35 -0700 Subject: [PATCH 4/4] And then add Smile impl --- release-notes/CREDITS | 6 +++--- release-notes/VERSION | 4 ++-- .../jackson/dataformat/smile/SmileMapper.java | 14 ++++++++++++++ .../dataformat/smile/SmileReadFeature.java | 2 ++ .../smile/mapper/MapperFeaturesTest.java | 16 ++++++++++++---- 5 files changed, 33 insertions(+), 9 deletions(-) diff --git a/release-notes/CREDITS b/release-notes/CREDITS index 67f409da2..f4be9d990 100644 --- a/release-notes/CREDITS +++ b/release-notes/CREDITS @@ -15,11 +15,11 @@ Fawzi Essam (@iifawzi) * Contributed #582: Change defaults for `CBORReadFeature.DECODE_USING_STANDARD_NEGATIVE_BIGINT_ENCODING` and `CBORWriteFeature.ENCODE_USING_STANDARD_NEGATIVE_BIGINT_ENCODING` to `true` (enabled) (3.0.0) -* Contribited #591: Change `CBOR` Features defaults for 3.0 +* Contributed #591: Change `CBOR` Features defaults for 3.0 (3.0.0) Andy Wilkinson (@wilkinsona) -* Requested #619: (avro, cbor) Add `isEnabled()` methods for format-specific features (like - `CBORReadFeature` and `CBORWriteFeature`) to mappers +* Requested #619: (avro, cbor, ion, smile) Add `isEnabled()` methods for format-specific features + (like `CBORReadFeature` and `CBORWriteFeature`) to mappers (3.1.0) diff --git a/release-notes/VERSION b/release-notes/VERSION index 18dbbb187..b0f66b7fd 100644 --- a/release-notes/VERSION +++ b/release-notes/VERSION @@ -16,8 +16,8 @@ implementations) 3.1.0 (not yet released) -#619: (avro, cbor, ion) Add `isEnabled()` methods for format-specific features (like - `CBORReadFeature` and `CBORWriteFeature`) to mappers +#619: (avro, cbor, ion, smile) Add `isEnabled()` methods for format-specific features + (like `CBORReadFeature` and `CBORWriteFeature`) to mappers (requested by Andy W) 3.0.1 (21-Oct-2025) diff --git a/smile/src/main/java/tools/jackson/dataformat/smile/SmileMapper.java b/smile/src/main/java/tools/jackson/dataformat/smile/SmileMapper.java index 55bbb107d..036401200 100644 --- a/smile/src/main/java/tools/jackson/dataformat/smile/SmileMapper.java +++ b/smile/src/main/java/tools/jackson/dataformat/smile/SmileMapper.java @@ -173,6 +173,20 @@ public SmileFactory tokenStreamFactory() { return (SmileFactory) _streamFactory; } + /* + /********************************************************************** + /* Format-specific + /********************************************************************** + */ + + public boolean isEnabled(SmileReadFeature f) { + return _deserializationConfig.hasFormatFeature(f); + } + + public boolean isEnabled(SmileWriteFeature f) { + return _serializationConfig.hasFormatFeature(f); + } + /* /********************************************************************** /* Helper class(es) diff --git a/smile/src/main/java/tools/jackson/dataformat/smile/SmileReadFeature.java b/smile/src/main/java/tools/jackson/dataformat/smile/SmileReadFeature.java index ea00d8489..1b9677187 100644 --- a/smile/src/main/java/tools/jackson/dataformat/smile/SmileReadFeature.java +++ b/smile/src/main/java/tools/jackson/dataformat/smile/SmileReadFeature.java @@ -14,6 +14,8 @@ public enum SmileReadFeature implements FormatFeature * or optional. If enabled, it means that only input that starts with the header * is accepted as valid; if disabled, header is optional. In latter case, * settings for content are assumed to be defaults. + *

+ * Feature is enabled by default. */ REQUIRE_HEADER(true) ; diff --git a/smile/src/test/java/tools/jackson/dataformat/smile/mapper/MapperFeaturesTest.java b/smile/src/test/java/tools/jackson/dataformat/smile/mapper/MapperFeaturesTest.java index 63830fd4a..4904ebdc8 100644 --- a/smile/src/test/java/tools/jackson/dataformat/smile/mapper/MapperFeaturesTest.java +++ b/smile/src/test/java/tools/jackson/dataformat/smile/mapper/MapperFeaturesTest.java @@ -3,15 +3,15 @@ import org.junit.jupiter.api.Test; import tools.jackson.databind.*; -import tools.jackson.dataformat.smile.BaseTestForSmile; -import tools.jackson.dataformat.smile.SmileFactory; -import tools.jackson.dataformat.smile.SmileMapper; + +import tools.jackson.dataformat.smile.*; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; public class MapperFeaturesTest extends BaseTestForSmile { - static class Bean { + public static class Bean { public int value; } @@ -35,4 +35,12 @@ public void testIndent() throws Exception Bean result = mapper.readValue(smile, 0, smile.length, Bean.class); assertEquals(42, result.value); } + + // [dataformats-binary#619] + @Test + void testFormatFeatureDefaults() { + SmileMapper mapper = SmileMapper.shared(); + assertTrue(mapper.isEnabled(SmileReadFeature.REQUIRE_HEADER)); + assertTrue(mapper.isEnabled(SmileWriteFeature.WRITE_HEADER)); + } }