Skip to content

Move jackson-datatype-jsr310 into jackson-databind #5032

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 27 commits into from
Apr 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
9744808
start of move
pjfanning Mar 18, 2025
0141457
tests
pjfanning Mar 18, 2025
b25ee25
move javatimefeature enable to mapperbuilder
pjfanning Mar 18, 2025
615f6f2
accidental edit (fixed)
pjfanning Mar 18, 2025
e5b0263
auto-enable JavaTimeModule - breaks a few tests
pjfanning Mar 18, 2025
e586ec5
remove code that warns if java.time classes are used but module is no…
pjfanning Mar 18, 2025
70d3194
remove JavaTimeModule
pjfanning Mar 18, 2025
d47a0e9
fix test - no longer fails because java.time is now supported out of …
pjfanning Mar 18, 2025
c78b6cb
Update POJONodeTest.java
pjfanning Mar 18, 2025
67e4154
make method private - class is final anyway
pjfanning Mar 18, 2025
30b97d8
Update module-info.java
pjfanning Mar 18, 2025
1393821
change package name
pjfanning Mar 19, 2025
27ef8b7
Merge branch 'master' into datetime
cowtowncoder Mar 20, 2025
0dd3dfc
Merge branch 'master' into datetime
cowtowncoder Mar 24, 2025
1be24ec
Merge branch 'master' into datetime
cowtowncoder Mar 26, 2025
27bafa4
Merge branch 'master' into datetime
cowtowncoder Mar 26, 2025
e8c7c99
Merge branch 'master' into datetime
cowtowncoder Mar 29, 2025
3d39a7f
Merge branch 'master' into datetime
cowtowncoder Apr 3, 2025
f4325b7
Merge https://github.com/FasterXML/jackson-modules-java8/issues/364 c…
cowtowncoder Apr 4, 2025
6f43389
Minor Javadoc improvements
cowtowncoder Apr 4, 2025
d6d8d04
Start conversion to make `JavaTimeFeature` be accessed via `DatatypeF…
cowtowncoder Apr 4, 2025
0f8a890
Bit of refactoring wrt JavaTimeFeature
cowtowncoder Apr 4, 2025
6432627
Minor refactoring
cowtowncoder Apr 4, 2025
6e25e80
Refactoring: change "ext.datetime" to "ext.javatime" wrt supported AP…
cowtowncoder Apr 4, 2025
765ca83
Minor javadoc improvements
cowtowncoder Apr 4, 2025
c5ffdd8
Rename JavaTimeFeature as DateTimeFeature for use with java.util/Joda…
cowtowncoder Apr 4, 2025
53303b9
Minor reordering
cowtowncoder Apr 4, 2025
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
5 changes: 5 additions & 0 deletions src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@
exports tools.jackson.databind.deser.std;
exports tools.jackson.databind.exc;
exports tools.jackson.databind.ext;
exports tools.jackson.databind.ext.javatime;
exports tools.jackson.databind.ext.javatime.deser;
exports tools.jackson.databind.ext.javatime.deser.key;
exports tools.jackson.databind.ext.javatime.ser;
exports tools.jackson.databind.ext.javatime.ser.key;
exports tools.jackson.databind.ext.jdk8;
// Needed by Ion module for SqlDate deserializer:
exports tools.jackson.databind.ext.sql;
Expand Down
6 changes: 4 additions & 2 deletions src/main/java/tools/jackson/databind/JacksonModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
import java.util.function.UnaryOperator;

import tools.jackson.core.*;
import tools.jackson.databind.cfg.MapperBuilder;
import tools.jackson.databind.cfg.MutableConfigOverride;
import tools.jackson.databind.cfg.*;
import tools.jackson.databind.deser.*;
import tools.jackson.databind.jsontype.NamedType;
import tools.jackson.databind.ser.Serializers;
Expand Down Expand Up @@ -146,6 +145,9 @@ public static interface SetupContext
public boolean isEnabled(TokenStreamFactory.Feature f);
public boolean isEnabled(StreamReadFeature f);
public boolean isEnabled(StreamWriteFeature f);
public boolean isEnabled(DatatypeFeature f);

public DatatypeFeatures datatypeFeatures();

/*
/******************************************************************
Expand Down
30 changes: 15 additions & 15 deletions src/main/java/tools/jackson/databind/SerializationFeature.java
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,21 @@ public enum SerializationFeature implements ConfigFeature
*/
WRITE_DATE_KEYS_AS_TIMESTAMPS(false),

/**
* Feature that controls whether numeric timestamp values are
* to be written using nanosecond timestamps (enabled) or not (disabled);
* <b>if and only if</b> datatype supports such resolution.
* Only newer datatypes (such as Java8 Date/Time) support such resolution --
* older types (pre-Java8 <b>java.util.Date</b> etc) and Joda do not --
* and this setting <b>has no effect</b> on such types.
*<p>
* If disabled, standard millisecond timestamps are assumed.
* This is the counterpart to {@link DeserializationFeature#READ_DATE_TIMESTAMPS_AS_NANOSECONDS}.
*<p>
* Feature is enabled by default, to support most accurate time values possible.
*/
WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS(true),

/**
* Feature that determines whether date/date-time values should be serialized
* so that they include timezone id, in cases where type itself contains
Expand Down Expand Up @@ -360,21 +375,6 @@ public enum SerializationFeature implements ConfigFeature
*/
WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED(false),

/**
* Feature that controls whether numeric timestamp values are
* to be written using nanosecond timestamps (enabled) or not (disabled);
* <b>if and only if</b> datatype supports such resolution.
* Only newer datatypes (such as Java8 Date/Time) support such resolution --
* older types (pre-Java8 <b>java.util.Date</b> etc) and Joda do not --
* and this setting <b>has no effect</b> on such types.
*<p>
* If disabled, standard millisecond timestamps are assumed.
* This is the counterpart to {@link DeserializationFeature#READ_DATE_TIMESTAMPS_AS_NANOSECONDS}.
*<p>
* Feature is enabled by default, to support most accurate time values possible.
*/
WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS(true),

/**
* Feature that determines whether {@link java.util.Map} entries are first
* sorted by key before serialization or not: if enabled, additional sorting
Expand Down
79 changes: 60 additions & 19 deletions src/main/java/tools/jackson/databind/cfg/DatatypeFeatures.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,31 +14,38 @@ public class DatatypeFeatures

protected final static int FEATURE_INDEX_ENUM = 0;
protected final static int FEATURE_INDEX_JSON_NODE = 1;
protected final static int FEATURE_INDEX_DATETIME = 2;

private final int _enabledFor1, _enabledFor2;
private final int _enabledFor1, _enabledFor2, _enabledFor3;

private final int _explicitFor1, _explicitFor2;
private final int _explicitFor1, _explicitFor2, _explicitFor3;

protected DatatypeFeatures(int enabledFor1, int explicitFor1,
int enabledFor2, int explicitFor2) {
int enabledFor2, int explicitFor2,
int enabledFor3, int explicitFor3) {
_enabledFor1 = enabledFor1;
_explicitFor1 = explicitFor1;
_enabledFor2 = enabledFor2;
_explicitFor2 = explicitFor2;
_enabledFor3 = enabledFor3;
_explicitFor3 = explicitFor3;
}

public static DatatypeFeatures defaultFeatures() {
return DefaultHolder.getDefault();
}

private DatatypeFeatures _with(int enabledFor1, int explicitFor1,
int enabledFor2, int explicitFor2) {
int enabledFor2, int explicitFor2,
int enabledFor3, int explicitFor3) {
if ((_enabledFor1 == enabledFor1) && (_explicitFor1 == explicitFor1)
&& (_enabledFor2 == enabledFor2) && (_explicitFor2 == explicitFor2)) {
&& (_enabledFor2 == enabledFor2) && (_explicitFor2 == explicitFor2)
&& (_enabledFor3 == enabledFor3) && (_explicitFor3 == explicitFor3)) {
return this;
}
return new DatatypeFeatures(enabledFor1, explicitFor1,
enabledFor2, explicitFor2);
enabledFor2, explicitFor2,
enabledFor3, explicitFor3);
}

/*
Expand All @@ -61,10 +68,16 @@ public DatatypeFeatures with(DatatypeFeature f) {
switch (f.featureIndex()) {
case 0:
return _with(_enabledFor1 | mask, _explicitFor1 | mask,
_enabledFor2, _explicitFor2);
_enabledFor2, _explicitFor2,
_enabledFor3, _explicitFor3);
case 1:
return _with(_enabledFor1, _explicitFor1,
_enabledFor2 | mask, _explicitFor2 | mask);
_enabledFor2 | mask, _explicitFor2 | mask,
_enabledFor3, _explicitFor3);
case 2:
return _with(_enabledFor1, _explicitFor1,
_enabledFor2, _explicitFor2,
_enabledFor3 | mask, _explicitFor3 | mask);
default:
VersionUtil.throwInternal();
return this;
Expand All @@ -88,10 +101,16 @@ public DatatypeFeatures withFeatures(DatatypeFeature... features) {
switch (features[0].featureIndex()) {
case 0:
return _with(_enabledFor1 | mask, _explicitFor1 | mask,
_enabledFor2, _explicitFor2);
_enabledFor2, _explicitFor2,
_enabledFor3, _explicitFor3);
case 1:
return _with(_enabledFor1, _explicitFor1,
_enabledFor2 | mask, _explicitFor2 | mask);
_enabledFor2 | mask, _explicitFor2 | mask,
_enabledFor3, _explicitFor3);
case 2:
return _with(_enabledFor1, _explicitFor1,
_enabledFor2, _explicitFor2,
_enabledFor3 | mask, _explicitFor3 | mask);
default:
VersionUtil.throwInternal();
return this;
Expand All @@ -112,10 +131,16 @@ public DatatypeFeatures without(DatatypeFeature f) {
switch (f.featureIndex()) {
case 0:
return _with(_enabledFor1 & ~mask, _explicitFor1 | mask,
_enabledFor2, _explicitFor2);
_enabledFor2, _explicitFor2,
_enabledFor3, _explicitFor3);
case 1:
return _with(_enabledFor1, _explicitFor1,
_enabledFor2 & ~mask, _explicitFor2 | mask);
_enabledFor2 & ~mask, _explicitFor2 | mask,
_enabledFor3, _explicitFor3);
case 2:
return _with(_enabledFor1, _explicitFor1,
_enabledFor2, _explicitFor2,
_enabledFor3 & ~mask, _explicitFor3 | mask);
default:
VersionUtil.throwInternal();
return this;
Expand All @@ -139,10 +164,16 @@ public DatatypeFeatures withoutFeatures(DatatypeFeature... features) {
switch (features[0].featureIndex()) {
case 0:
return _with(_enabledFor1 & ~mask, _explicitFor1 | mask,
_enabledFor2, _explicitFor2);
_enabledFor2, _explicitFor2,
_enabledFor3, _explicitFor3);
case 1:
return _with(_enabledFor1, _explicitFor1,
_enabledFor2 & ~mask, _explicitFor2 | mask);
_enabledFor2 & ~mask, _explicitFor2 | mask,
_enabledFor3, _explicitFor3);
case 2:
return _with(_enabledFor1, _explicitFor1,
_enabledFor2, _explicitFor2,
_enabledFor3 & ~mask, _explicitFor3 | mask);
default:
VersionUtil.throwInternal();
return this;
Expand Down Expand Up @@ -179,6 +210,8 @@ public boolean isEnabled(DatatypeFeature f) {
return f.enabledIn(_enabledFor1);
case 1:
return f.enabledIn(_enabledFor2);
case 2:
return f.enabledIn(_enabledFor3);
default:
VersionUtil.throwInternal();
return false;
Expand All @@ -200,6 +233,8 @@ public boolean isExplicitlySet(DatatypeFeature f) {
return f.enabledIn(_explicitFor1);
case 1:
return f.enabledIn(_explicitFor2);
case 2:
return f.enabledIn(_explicitFor3);
default:
VersionUtil.throwInternal();
return false;
Expand All @@ -215,15 +250,15 @@ public boolean isExplicitlySet(DatatypeFeature f) {
* @param f Feature to check
*
* @return Whether given feature has been explicitly enabled
*
* @since 2.15
*/
public boolean isExplicitlyEnabled(DatatypeFeature f) {
switch (f.featureIndex()) {
case 0:
return f.enabledIn(_explicitFor1 & _enabledFor1);
case 1:
return f.enabledIn(_explicitFor2 & _enabledFor2);
case 2:
return f.enabledIn(_explicitFor3 & _enabledFor3);
default:
VersionUtil.throwInternal();
return false;
Expand All @@ -239,15 +274,15 @@ public boolean isExplicitlyEnabled(DatatypeFeature f) {
* @param f Feature to check
*
* @return Whether given feature has been explicitly disabled
*
* @since 2.15
*/
public boolean isExplicitlyDisabled(DatatypeFeature f) {
switch (f.featureIndex()) {
case 0:
return f.enabledIn(_explicitFor1 & ~_enabledFor1);
case 1:
return f.enabledIn(_explicitFor2 & ~_enabledFor2);
case 2:
return f.enabledIn(_explicitFor3 & ~_enabledFor3);
default:
VersionUtil.throwInternal();
return false;
Expand Down Expand Up @@ -276,6 +311,11 @@ public Boolean getExplicitState(DatatypeFeature f) {
return f.enabledIn(_enabledFor2);
}
return null;
case 2:
if (f.enabledIn(_explicitFor3)) {
return f.enabledIn(_enabledFor3);
}
return null;
default:
VersionUtil.throwInternal();
return null;
Expand All @@ -298,7 +338,8 @@ private static class DefaultHolder
static {
DEFAULT_FEATURES = new DatatypeFeatures(
collectDefaults(EnumFeature.values()), 0,
collectDefaults(JsonNodeFeature.values()), 0
collectDefaults(JsonNodeFeature.values()), 0,
collectDefaults(DateTimeFeature.values()), 0
);
}

Expand Down
84 changes: 84 additions & 0 deletions src/main/java/tools/jackson/databind/cfg/DateTimeFeature.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package tools.jackson.databind.cfg;

/**
* Configurable on/off features to configure Date/Time handling.
* Mostly used to configure
* Java 8 Time ({@code java.time}) type handling (see
* {@link tools.jackson.databind.ext.javatime.JavaTimeInitializer})
* but also to "legacy" ({@link java.util.Date}, {@link java.util.Calendar})
* and Joda Date/Time.
*/
public enum DateTimeFeature implements DatatypeFeature
{
/**
* Feature that determines whether {@link java.time.ZoneId} is normalized
* (via call to {@code java.time.ZoneId#normalized()}) when deserializing
* types like {@link java.time.ZonedDateTime}.
*<p>
* Default setting is enabled, for backwards-compatibility with
* Jackson 2.15.
*/
NORMALIZE_DESERIALIZED_ZONE_ID(true),

/**
* Feature that determines whether the {@link java.util.TimeZone} of the
* {@link tools.jackson.databind.DeserializationContext} is used
* when leniently deserializing {@link java.time.LocalDate} or
* {@link java.time.LocalDateTime} from the UTC/ISO instant format.
* <p>
* Default setting is disabled, for backwards-compatibility with
* Jackson 2.18.
*
* @since 2.19
*/
USE_TIME_ZONE_FOR_LENIENT_DATE_PARSING(false),

/**
* Feature that controls whether stringified numbers (Strings that without
* quotes would be legal JSON Numbers) may be interpreted as
* timestamps (enabled) or not (disabled), in case where there is an
* explicitly defined pattern ({@code DateTimeFormatter}, usually by
* using {@code @JsonFormat} annotation) for value.
* <p>
* Note that when the default pattern is used (no custom pattern defined),
* stringified numbers are always accepted as timestamps regardless of
* this feature.
*/
ALWAYS_ALLOW_STRINGIFIED_DATE_TIMESTAMPS(false),

/**
* Feature that determines whether {@link java.time.Month} is serialized
* and deserialized as using a zero-based index (FALSE) or a one-based index (TRUE).
* For example, "1" would be serialized/deserialized as Month.JANUARY if TRUE and Month.FEBRUARY if FALSE.
*<p>
* Default setting is false, meaning that Month is serialized/deserialized as a zero-based index.
*/
ONE_BASED_MONTHS(false)
;

private final static int FEATURE_INDEX = DatatypeFeatures.FEATURE_INDEX_DATETIME;

/**
* Whether feature is enabled or disabled by default.
*/
private final boolean _enabledByDefault;

private final int _mask;

private DateTimeFeature(boolean enabledByDefault) {
_enabledByDefault = enabledByDefault;
_mask = (1 << ordinal());
}

@Override
public boolean enabledByDefault() { return _enabledByDefault; }
@Override
public boolean enabledIn(int flags) { return (flags & _mask) != 0; }
@Override
public int getMask() { return _mask; }

@Override
public int featureIndex() {
return FEATURE_INDEX;
}
}
5 changes: 3 additions & 2 deletions src/main/java/tools/jackson/databind/cfg/MapperBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import tools.jackson.core.util.Snapshottable;
import tools.jackson.databind.*;
import tools.jackson.databind.deser.*;
import tools.jackson.databind.ext.javatime.JavaTimeInitializer;
import tools.jackson.databind.introspect.*;
import tools.jackson.databind.jsontype.*;
import tools.jackson.databind.jsontype.impl.DefaultTypeResolverBuilder;
Expand Down Expand Up @@ -419,8 +420,9 @@ public MapperBuilderState saveStateApplyModules()
{
if (_savedState == null) {
_savedState = _saveState();
ModuleContextBase ctxt = _constructModuleContext();
JavaTimeInitializer.getInstance().setupModule(ctxt);
if (_modules != null) {
ModuleContextBase ctxt = _constructModuleContext();
_modules.values().forEach(m -> m.setupModule(ctxt));
// and since context may buffer some changes, ensure those are flushed:
ctxt.applyChanges(this);
Expand Down Expand Up @@ -485,7 +487,6 @@ public boolean isEnabled(SerializationFeature f) {
public boolean isEnabled(DatatypeFeature f) {
return _datatypeFeatures.isEnabled(f);
}

public boolean isEnabled(StreamReadFeature f) {
return f.enabledIn(_streamReadFeatures);
}
Expand Down
Loading