From f80bfd0579189542857a706b740df19c7982023e Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Wed, 5 Mar 2025 10:37:56 +0100 Subject: [PATCH 1/7] Jackson3: add setJackson2Defaults() to JsonFactoryBuilder --- .../tools/jackson/core/json/JsonFactoryBuilder.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/main/java/tools/jackson/core/json/JsonFactoryBuilder.java b/src/main/java/tools/jackson/core/json/JsonFactoryBuilder.java index 7ecdc45608..80a58bcca7 100644 --- a/src/main/java/tools/jackson/core/json/JsonFactoryBuilder.java +++ b/src/main/java/tools/jackson/core/json/JsonFactoryBuilder.java @@ -116,6 +116,19 @@ public JsonFactoryBuilder configure(JsonWriteFeature f, boolean state) { return state ? enable(f) : disable(f); } + /** + * Modifies the settings of this builder to more closely match the default configs used + * in Jackson 2.x versions. + *

+ * This method is still a work in progress and may not yet fully replicate the + * default settings of Jackson 2.x. + *

+ */ + public JsonFactoryBuilder setJackson2Defaults() { + return disable(JsonWriteFeature.ESCAPE_FORWARD_SLASHES) + .disable(JsonWriteFeature.COMBINE_UNICODE_SURROGATES_IN_UTF8); + } + // // // Other JSON-specific configuration /** From 218bb2993bd53954f5cee20d31a0e866f4b859fa Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Wed, 5 Mar 2025 10:58:38 +0100 Subject: [PATCH 2/7] more settings --- src/main/java/tools/jackson/core/StreamWriteFeature.java | 2 +- src/main/java/tools/jackson/core/json/JsonFactoryBuilder.java | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/tools/jackson/core/StreamWriteFeature.java b/src/main/java/tools/jackson/core/StreamWriteFeature.java index 180982ea9a..eb76567d13 100644 --- a/src/main/java/tools/jackson/core/StreamWriteFeature.java +++ b/src/main/java/tools/jackson/core/StreamWriteFeature.java @@ -122,7 +122,7 @@ public enum StreamWriteFeature * NOTE! Enabling this feature appears to improve performance significantly * up to and including JDK 17, but NOT when using JDK 21 * and above -- in fact, it seems that JDK implementation is slightly faster. - * Because of this,enabling this feature is only recommended for JDKs 17 and below. + * Because of this, enabling this feature is only recommended for JDKs 17 and below. *

* Feature is disabled by default, meaning that JDK default conversions are used. */ diff --git a/src/main/java/tools/jackson/core/json/JsonFactoryBuilder.java b/src/main/java/tools/jackson/core/json/JsonFactoryBuilder.java index 80a58bcca7..cc729f014f 100644 --- a/src/main/java/tools/jackson/core/json/JsonFactoryBuilder.java +++ b/src/main/java/tools/jackson/core/json/JsonFactoryBuilder.java @@ -126,7 +126,9 @@ public JsonFactoryBuilder configure(JsonWriteFeature f, boolean state) { */ public JsonFactoryBuilder setJackson2Defaults() { return disable(JsonWriteFeature.ESCAPE_FORWARD_SLASHES) - .disable(JsonWriteFeature.COMBINE_UNICODE_SURROGATES_IN_UTF8); + .disable(JsonWriteFeature.COMBINE_UNICODE_SURROGATES_IN_UTF8) + .disable(StreamReadFeature.USE_FAST_DOUBLE_PARSER) + .disable(StreamReadFeature.USE_FAST_BIG_NUMBER_PARSER); } // // // Other JSON-specific configuration From 4542a2ab2ef772a7456fd9b27075b342ead09d7c Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Wed, 5 Mar 2025 21:31:30 +0100 Subject: [PATCH 3/7] move method to JsonFactory --- .../tools/jackson/core/json/JsonFactory.java | 22 ++++++++++-- .../jackson/core/json/JsonFactoryBuilder.java | 15 -------- .../core/unittest/json/JsonFactoryTest.java | 35 ++++++++++++++++++- 3 files changed, 54 insertions(+), 18 deletions(-) diff --git a/src/main/java/tools/jackson/core/json/JsonFactory.java b/src/main/java/tools/jackson/core/json/JsonFactory.java index 430cad5cde..344c404cc7 100644 --- a/src/main/java/tools/jackson/core/json/JsonFactory.java +++ b/src/main/java/tools/jackson/core/json/JsonFactory.java @@ -183,14 +183,32 @@ public JsonFactoryBuilder rebuild() { /** * Main factory method to use for constructing {@link JsonFactory} instances with - * different configuration. - * + * different configuration. The builder returned uses default settings more closely + * matched the default configs used in Jackson 2.x versions. + *

+ * This method is still a work in progress and may not yet fully replicate the + * default settings of Jackson 2.x. + *

* @return Builder instance to use */ public static JsonFactoryBuilder builder() { return new JsonFactoryBuilder(); } + /** + * Factory method to use for constructing {@link JsonFactory} instances with + * different configuration. + * + * @return Builder instance to use + */ + public static JsonFactoryBuilder builderWithJackson2Defaults() { + return builder() + .disable(JsonWriteFeature.ESCAPE_FORWARD_SLASHES) + .disable(JsonWriteFeature.COMBINE_UNICODE_SURROGATES_IN_UTF8) + .disable(StreamReadFeature.USE_FAST_DOUBLE_PARSER) + .disable(StreamReadFeature.USE_FAST_BIG_NUMBER_PARSER); + } + /** * Method for constructing a new {@link JsonFactory} that has * the same settings as this instance, but is otherwise diff --git a/src/main/java/tools/jackson/core/json/JsonFactoryBuilder.java b/src/main/java/tools/jackson/core/json/JsonFactoryBuilder.java index cc729f014f..7ecdc45608 100644 --- a/src/main/java/tools/jackson/core/json/JsonFactoryBuilder.java +++ b/src/main/java/tools/jackson/core/json/JsonFactoryBuilder.java @@ -116,21 +116,6 @@ public JsonFactoryBuilder configure(JsonWriteFeature f, boolean state) { return state ? enable(f) : disable(f); } - /** - * Modifies the settings of this builder to more closely match the default configs used - * in Jackson 2.x versions. - *

- * This method is still a work in progress and may not yet fully replicate the - * default settings of Jackson 2.x. - *

- */ - public JsonFactoryBuilder setJackson2Defaults() { - return disable(JsonWriteFeature.ESCAPE_FORWARD_SLASHES) - .disable(JsonWriteFeature.COMBINE_UNICODE_SURROGATES_IN_UTF8) - .disable(StreamReadFeature.USE_FAST_DOUBLE_PARSER) - .disable(StreamReadFeature.USE_FAST_BIG_NUMBER_PARSER); - } - // // // Other JSON-specific configuration /** diff --git a/src/test/java/tools/jackson/core/unittest/json/JsonFactoryTest.java b/src/test/java/tools/jackson/core/unittest/json/JsonFactoryTest.java index 93965b4469..6c9970ec0f 100644 --- a/src/test/java/tools/jackson/core/unittest/json/JsonFactoryTest.java +++ b/src/test/java/tools/jackson/core/unittest/json/JsonFactoryTest.java @@ -4,6 +4,7 @@ import java.nio.charset.StandardCharsets; import java.nio.file.*; +import org.junit.jupiter.api.Test; import tools.jackson.core.FormatSchema; import tools.jackson.core.JsonEncoding; import tools.jackson.core.JsonGenerator; @@ -11,6 +12,7 @@ import tools.jackson.core.JsonToken; import tools.jackson.core.ObjectReadContext; import tools.jackson.core.ObjectWriteContext; +import tools.jackson.core.StreamReadFeature; import tools.jackson.core.StreamWriteFeature; import tools.jackson.core.TokenStreamFactory; import tools.jackson.core.io.SerializedString; @@ -42,6 +44,7 @@ public String getSchemaType() { private final JsonFactory JSON_F = newStreamFactory(); + @Test public void testStreamWriteFeatures() throws Exception { JsonFactory f = JsonFactory.builder() @@ -53,6 +56,7 @@ public void testStreamWriteFeatures() throws Exception assertFalse(f.isEnabled(StreamWriteFeature.IGNORE_UNKNOWN)); } + @Test public void testJsonWriteFeatures() throws Exception { JsonFactory f = JsonFactory.builder() @@ -64,6 +68,7 @@ public void testJsonWriteFeatures() throws Exception assertFalse(f.isEnabled(JsonWriteFeature.QUOTE_PROPERTY_NAMES)); } + @Test public void testFactoryFeatures() throws Exception { JsonFactory f = JsonFactory.builder() @@ -79,6 +84,7 @@ public void testFactoryFeatures() throws Exception assertFalse(f.canHandleBinaryNatively()); } + @Test public void testFactoryMisc() throws Exception { assertNull(JSON_F.getInputDecorator()); @@ -91,6 +97,7 @@ public void testFactoryMisc() throws Exception assertEquals(JsonWriteFeature.class, JSON_F.getFormatWriteFeatureType()); } + @Test public void testJsonWithFiles() throws Exception { File file = File.createTempFile("jackson-test", null); @@ -123,6 +130,7 @@ public void testJsonWithFiles() throws Exception file.delete(); } + @Test public void testCopy() throws Exception { JsonFactory f = new JsonFactory(); @@ -149,6 +157,7 @@ public void testCopy() throws Exception assertTrue(f.isEnabled(JsonWriteFeature.ESCAPE_NON_ASCII)); } + @Test public void testRootValues() throws Exception { assertEquals(" ", JSON_F.getRootValueSeparator()); @@ -168,6 +177,7 @@ public void testRootValues() throws Exception assertEquals("1/2/3", w.toString()); } + @Test public void test_createGenerator_OutputStream() throws Exception { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); @@ -183,6 +193,7 @@ public void test_createGenerator_OutputStream() throws Exception outputStream.write(1); } + @Test public void test_createGenerator_File() throws Exception { Path path = Files.createTempFile("", ""); @@ -195,6 +206,7 @@ public void test_createGenerator_File() throws Exception assertEquals(new String(Files.readAllBytes(path), StandardCharsets.UTF_8), "\"value\""); } + @Test public void test_createGenerator_Path() throws Exception { Path path = Files.createTempFile("", ""); @@ -207,6 +219,7 @@ public void test_createGenerator_Path() throws Exception assertEquals(new String(Files.readAllBytes(path), StandardCharsets.UTF_8), "\"value\""); } + @Test public void test_createGenerator_Writer() throws Exception { Writer writer = new StringWriter(); @@ -222,6 +235,7 @@ public void test_createGenerator_Writer() throws Exception writer.append('1'); } + @Test public void test_createGenerator_DataOutput() throws Exception { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); @@ -238,6 +252,7 @@ public void test_createGenerator_DataOutput() throws Exception dataOutput.write(1); } + @Test public void test_createParser_InputStream() throws Exception { InputStream inputStream = new ByteArrayInputStream("\"value\"".getBytes(StandardCharsets.UTF_8)); @@ -247,6 +262,7 @@ public void test_createParser_InputStream() throws Exception assertEquals(jsonParser.nextStringValue(), "value"); } + @Test public void test_createParser_File() throws Exception { Path path = Files.createTempFile("", ""); @@ -257,6 +273,7 @@ public void test_createParser_File() throws Exception assertEquals(jsonParser.nextStringValue(), "value"); } + @Test public void test_createParser_Path() throws Exception { Path path = Files.createTempFile("", ""); @@ -267,6 +284,7 @@ public void test_createParser_Path() throws Exception assertEquals(jsonParser.nextStringValue(), "value"); } + @Test public void test_createParser_Url() throws Exception { Path path = Files.createTempFile("", ""); @@ -277,6 +295,7 @@ public void test_createParser_Url() throws Exception assertEquals(jsonParser.nextStringValue(), "value"); } + @Test public void test_createParser_Reader() throws Exception { Reader reader = new StringReader("\"value\""); @@ -286,6 +305,7 @@ public void test_createParser_Reader() throws Exception assertEquals(jsonParser.nextStringValue(), "value"); } + @Test public void test_createParser_ByteArray() throws Exception { byte[] bytes = "\"value\"".getBytes(StandardCharsets.UTF_8); @@ -295,6 +315,7 @@ public void test_createParser_ByteArray() throws Exception assertEquals(jsonParser.nextStringValue(), "value"); } + @Test public void test_createParser_String() throws Exception { String string = "\"value\""; @@ -304,6 +325,7 @@ public void test_createParser_String() throws Exception assertEquals(jsonParser.nextStringValue(), "value"); } + @Test public void test_createParser_CharArray() throws Exception { char[] chars = "\"value\"".toCharArray(); @@ -313,6 +335,7 @@ public void test_createParser_CharArray() throws Exception assertEquals(jsonParser.nextStringValue(), "value"); } + @Test public void test_createParser_DataInput() throws Exception { InputStream inputStream = new ByteArrayInputStream("\"value\"".getBytes(StandardCharsets.UTF_8)); @@ -323,15 +346,25 @@ public void test_createParser_DataInput() throws Exception assertEquals(jsonParser.nextStringValue(), "value"); } - + @Test public void testCanonicalizationEnabled() throws Exception { doCanonicalizationTest(false); } + @Test public void testCanonicalizationDisabled() throws Exception { doCanonicalizationTest(false); } + @Test + public void testBuilderWithJackson2Defaults() { + JsonFactory factory = JsonFactory.builderWithJackson2Defaults().build(); + assertFalse(factory.isEnabled(StreamReadFeature.USE_FAST_DOUBLE_PARSER)); + assertFalse(factory.isEnabled(StreamReadFeature.USE_FAST_BIG_NUMBER_PARSER)); + assertFalse(factory.isEnabled(JsonWriteFeature.ESCAPE_FORWARD_SLASHES)); + assertFalse(factory.isEnabled(JsonWriteFeature.COMBINE_UNICODE_SURROGATES_IN_UTF8)); + } + // Configure the JsonFactory as expected, and verify across common shapes of input // to cover common JsonParser implementations. private void doCanonicalizationTest(boolean canonicalize) throws Exception { From d64078ffe53df1752d5da231ed63b143d70c8985 Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Wed, 5 Mar 2025 22:57:09 +0100 Subject: [PATCH 4/7] fix javadoc --- .../java/tools/jackson/core/json/JsonFactory.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/main/java/tools/jackson/core/json/JsonFactory.java b/src/main/java/tools/jackson/core/json/JsonFactory.java index 344c404cc7..7660910adf 100644 --- a/src/main/java/tools/jackson/core/json/JsonFactory.java +++ b/src/main/java/tools/jackson/core/json/JsonFactory.java @@ -183,12 +183,8 @@ public JsonFactoryBuilder rebuild() { /** * Main factory method to use for constructing {@link JsonFactory} instances with - * different configuration. The builder returned uses default settings more closely - * matched the default configs used in Jackson 2.x versions. - *

- * This method is still a work in progress and may not yet fully replicate the - * default settings of Jackson 2.x. - *

+ * different configuration. + * * @return Builder instance to use */ public static JsonFactoryBuilder builder() { @@ -197,7 +193,12 @@ public static JsonFactoryBuilder builder() { /** * Factory method to use for constructing {@link JsonFactory} instances with - * different configuration. + * different configuration. The builder returned uses default settings more closely + * matched the default configs used in Jackson 2.x versions. + *

+ * This method is still a work in progress and may not yet fully replicate the + * default settings of Jackson 2.x. + *

* * @return Builder instance to use */ From e46f3c174311e92baf2ac55b6acc1ae92d763bc3 Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Wed, 5 Mar 2025 22:58:38 +0100 Subject: [PATCH 5/7] Update JsonFactory.java --- src/main/java/tools/jackson/core/json/JsonFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/tools/jackson/core/json/JsonFactory.java b/src/main/java/tools/jackson/core/json/JsonFactory.java index 7660910adf..4055223a25 100644 --- a/src/main/java/tools/jackson/core/json/JsonFactory.java +++ b/src/main/java/tools/jackson/core/json/JsonFactory.java @@ -194,7 +194,7 @@ public static JsonFactoryBuilder builder() { /** * Factory method to use for constructing {@link JsonFactory} instances with * different configuration. The builder returned uses default settings more closely - * matched the default configs used in Jackson 2.x versions. + * matching the default configs used in Jackson 2.x versions. *

* This method is still a work in progress and may not yet fully replicate the * default settings of Jackson 2.x. From 4131d0c7262b34aaa97f66941881792d221de8ef Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Thu, 6 Mar 2025 00:03:10 +0100 Subject: [PATCH 6/7] add configureForJackson2() --- src/main/java/tools/jackson/core/TSFBuilder.java | 13 +++++++++++++ .../java/tools/jackson/core/json/JsonFactory.java | 6 +----- .../tools/jackson/core/json/JsonFactoryBuilder.java | 7 +++++++ 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/main/java/tools/jackson/core/TSFBuilder.java b/src/main/java/tools/jackson/core/TSFBuilder.java index ed9465c152..dd385d6e5e 100644 --- a/src/main/java/tools/jackson/core/TSFBuilder.java +++ b/src/main/java/tools/jackson/core/TSFBuilder.java @@ -192,6 +192,19 @@ public B configure(StreamWriteFeature f, boolean state) { return state ? enable(f) : disable(f); } + /** + * The builder returned uses default settings more closely + * matching the default configs used in Jackson 2.x versions. + *

+ * This method is still a work in progress and may not yet fully replicate the + * default settings of Jackson 2.x. + *

+ */ + public B configureForJackson2() { + return disable(StreamReadFeature.USE_FAST_DOUBLE_PARSER) + .disable(StreamReadFeature.USE_FAST_BIG_NUMBER_PARSER); + } + // // // Other configuration, constraints /** diff --git a/src/main/java/tools/jackson/core/json/JsonFactory.java b/src/main/java/tools/jackson/core/json/JsonFactory.java index 4055223a25..57470ad613 100644 --- a/src/main/java/tools/jackson/core/json/JsonFactory.java +++ b/src/main/java/tools/jackson/core/json/JsonFactory.java @@ -203,11 +203,7 @@ public static JsonFactoryBuilder builder() { * @return Builder instance to use */ public static JsonFactoryBuilder builderWithJackson2Defaults() { - return builder() - .disable(JsonWriteFeature.ESCAPE_FORWARD_SLASHES) - .disable(JsonWriteFeature.COMBINE_UNICODE_SURROGATES_IN_UTF8) - .disable(StreamReadFeature.USE_FAST_DOUBLE_PARSER) - .disable(StreamReadFeature.USE_FAST_BIG_NUMBER_PARSER); + return builder().configureForJackson2(); } /** diff --git a/src/main/java/tools/jackson/core/json/JsonFactoryBuilder.java b/src/main/java/tools/jackson/core/json/JsonFactoryBuilder.java index 7ecdc45608..679fd9c48b 100644 --- a/src/main/java/tools/jackson/core/json/JsonFactoryBuilder.java +++ b/src/main/java/tools/jackson/core/json/JsonFactoryBuilder.java @@ -116,6 +116,13 @@ public JsonFactoryBuilder configure(JsonWriteFeature f, boolean state) { return state ? enable(f) : disable(f); } + @Override + public JsonFactoryBuilder configureForJackson2() { + return super.configureForJackson2() + .disable(JsonWriteFeature.ESCAPE_FORWARD_SLASHES) + .disable(JsonWriteFeature.COMBINE_UNICODE_SURROGATES_IN_UTF8); + } + // // // Other JSON-specific configuration /** From ef74fea6c7684bd34a6ead6e3aa4c7fb0ceca7bd Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Wed, 5 Mar 2025 19:22:44 -0800 Subject: [PATCH 7/7] Add release notes --- release-notes/VERSION | 3 +++ 1 file changed, 3 insertions(+) diff --git a/release-notes/VERSION b/release-notes/VERSION index 564b8a87e8..f3ec9fca93 100644 --- a/release-notes/VERSION +++ b/release-notes/VERSION @@ -53,6 +53,9 @@ JSON library. #1385: Create `jackson-core-[VERSION]-tests.jar` to contain shared test utility classes #1401: Rename `TreeNode.isContainerNode()` as `isContainer()` (3.0) +#1411: Add `JsonFactoryBuilder.configureForJackson2()`, + `JsonFactoryBuilder builderWithJackson2Defaults()` + (fixed by @pjfanning) - Rename `JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT` as `AUTO_CLOSE_CONTENT` - Add `TreeCodec.nullNode()`, `TreeNode.isNull()` methods - Change the way `JsonLocation.NA` is included in exception messages