Skip to content

Add JsonMapper.builderWithJackson2Defaults() #5004

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 6 commits into from
Mar 6, 2025
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 @@ -318,7 +318,7 @@ public enum DeserializationFeature implements ConfigFeature
* <p>
* NOTE: only <b>single</b> wrapper Array is allowed: if multiple attempted, exception
* will be thrown.
*
* <p>
* Feature is disabled by default.
*/
UNWRAP_SINGLE_VALUE_ARRAYS(false),
Expand All @@ -330,7 +330,7 @@ public enum DeserializationFeature implements ConfigFeature
* a single property with expected root name. If not, a
* {@link DatabindException} is thrown; otherwise value of the wrapped property
* will be deserialized as if it was the root value.
*<p>
* <p>
* Feature is disabled by default.
*/
UNWRAP_ROOT_VALUE(false),
Expand Down
19 changes: 19 additions & 0 deletions src/main/java/tools/jackson/databind/cfg/MapperBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,25 @@ public B configure(DatatypeFeature feature, boolean state) {
return _this();
}

/**
* The builder returned uses default settings more closely
* matching the default configs used in Jackson 2.x versions.
* <p>
* This method is still a work in progress and may not yet fully replicate the
* default settings of Jackson 2.x.
* </p>
*/
public B configureForJackson2() {
return enable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
.enable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.enable(SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS)
.disable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING)
.enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
.disable(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES)
.disable(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)
.disable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
}

/*
/**********************************************************************
/* Changing features: parser, generator
Expand Down
18 changes: 16 additions & 2 deletions src/main/java/tools/jackson/databind/json/JsonMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -142,17 +142,31 @@ public JsonMapper(Builder b) {
/**********************************************************************
*/

public static JsonMapper.Builder builder() {
public static Builder builder() {
return new Builder(new JsonFactory());
}

public static Builder builder(JsonFactory streamFactory) {
return new Builder(streamFactory);
}

/**
* Modifies the settings of this builder to more closely match the default configs used
* in Jackson 2.x versions.
* <p>
* This method is still a work in progress and may not yet fully replicate the
* default settings of Jackson 2.x.
* </p>
*/
public static Builder builderWithJackson2Defaults() {
return builder(JsonFactory.builderWithJackson2Defaults().build())
.configureForJackson2();
}


@SuppressWarnings("unchecked")
@Override
public JsonMapper.Builder rebuild() {
public Builder rebuild() {
return new Builder((Builder.StateImpl)_savedBuilderState);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package tools.jackson.databind.json;

import org.junit.jupiter.api.Test;
import tools.jackson.core.StreamReadFeature;
import tools.jackson.core.json.JsonFactory;
import tools.jackson.core.json.JsonWriteFeature;
import tools.jackson.databind.DeserializationFeature;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.SerializationFeature;
import tools.jackson.databind.testutil.DatabindTestUtil;

import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

// Test(s) to verify behaviors in JsonMapper.Builder
public class JsonMapperBuilderTest extends DatabindTestUtil
{

@Test
public void testBuilderWithJackson2Defaults()
{
ObjectMapper mapper = JsonMapper.builderWithJackson2Defaults().build();
JsonFactory jsonFactory = (JsonFactory) mapper.tokenStreamFactory();
assertFalse(mapper.isEnabled(StreamReadFeature.USE_FAST_DOUBLE_PARSER));
Copy link
Member

Choose a reason for hiding this comment

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

Should also not verify streaming-level setting at databind level.

Copy link
Member Author

Choose a reason for hiding this comment

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

People who want max Jackson2 compatibility will want mapper and factory level Jackson2-like config.

Copy link
Member

Choose a reason for hiding this comment

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

Yes, but it must be done at correct level -- streaming at streaming, databind at databind. Not with overlap.

Copy link
Member Author

Choose a reason for hiding this comment

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

JsonMapper.builderWithJackson2Defaults() is a high level method that creates a factory for you.

I have modified the lower level configureForJackson2 methods not to set factory level configs.

assertFalse(mapper.isEnabled(StreamReadFeature.USE_FAST_BIG_NUMBER_PARSER));
assertFalse(jsonFactory.isEnabled(JsonWriteFeature.ESCAPE_FORWARD_SLASHES));
assertFalse(jsonFactory.isEnabled(JsonWriteFeature.COMBINE_UNICODE_SURROGATES_IN_UTF8));
assertTrue(mapper.isEnabled(SerializationFeature.FAIL_ON_EMPTY_BEANS));
assertTrue(mapper.isEnabled(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS));
assertTrue(mapper.isEnabled(SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS));
assertFalse(mapper.isEnabled(SerializationFeature.WRITE_ENUMS_USING_TO_STRING));
assertTrue(mapper.isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES));
assertFalse(mapper.isEnabled(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES));
assertFalse(mapper.isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS));
assertFalse(mapper.isEnabled(DeserializationFeature.READ_ENUMS_USING_TO_STRING));
}
}