Skip to content

Commit

Permalink
Minor tweaks to #196, update release notes
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed Jan 8, 2021
1 parent 32f3f41 commit d475ed1
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.datatype.jsr310.DecimalUtils;

import java.io.IOException;
Expand All @@ -37,6 +35,7 @@
import java.time.format.DateTimeFormatter;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAccessor;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.regex.Pattern;
Expand Down Expand Up @@ -181,23 +180,17 @@ protected InstantDeserializer<T> withLeniency(Boolean leniency) {
protected InstantDeserializer<T> withShape(JsonFormat.Shape shape) { return this; }

@SuppressWarnings("unchecked")
@Override
public JsonDeserializer<T> createContextual(DeserializationContext ctxt,
BeanProperty property) throws JsonMappingException
@Override // @since 2.12.1
protected JSR310DateTimeDeserializerBase<?> _withFormatOverrides(DeserializationContext ctxt,
BeanProperty property, JsonFormat.Value formatOverrides)
{
InstantDeserializer<T> deserializer =
(InstantDeserializer<T>)super.createContextual(ctxt, property);
JsonFormat.Value val = findFormatOverrides(ctxt, property, handledType());
if (val != null) {
deserializer = new InstantDeserializer<>(deserializer, val.getFeature(JsonFormat.Feature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE));
if (val.hasLenient()) {
Boolean leniency = val.getLenient();
if (leniency != null) {
deserializer = deserializer.withLeniency(leniency);
}
}
InstantDeserializer<T> deser = (InstantDeserializer<T>) super._withFormatOverrides(ctxt,
property, formatOverrides);
Boolean B = formatOverrides.getFeature(JsonFormat.Feature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
if (!Objects.equals(B, deser._adjustToContextTZOverride)) {
return new InstantDeserializer<T>(deser, B);
}
return deserializer;
return deser;
}

@SuppressWarnings("unchecked")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,53 +101,70 @@ public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
BeanProperty property) throws JsonMappingException
{
JsonFormat.Value format = findFormatOverrides(ctxt, property, handledType());
return (format == null) ? this : _withFormatOverrides(ctxt, property, format);
}

/**
* @param ctxt Active deserialization context
* @param property (optional) Property on which this deserializer is used, or {@code null}
* for root value
* @param formatOverrides Format overrides to use (non-null)
*
* @return Either this deserializer as is, or newly constructed variant if created
* for different configuration
*
* @since 2.12.1
*/
protected JSR310DateTimeDeserializerBase<?> _withFormatOverrides(DeserializationContext ctxt,
BeanProperty property, JsonFormat.Value formatOverrides)
{
JSR310DateTimeDeserializerBase<?> deser = this;
if (format != null) {
// 17-Aug-2019, tatu: For 2.10 let's start considering leniency/strictness too
if (format.hasLenient()) {
Boolean leniency = format.getLenient();
if (leniency != null) {
deser = deser.withLeniency(leniency);
}

// 17-Aug-2019, tatu: For 2.10 let's start considering leniency/strictness too
if (formatOverrides.hasLenient()) {
Boolean leniency = formatOverrides.getLenient();
if (leniency != null) {
deser = deser.withLeniency(leniency);
}
if (format.hasPattern()) {
final String pattern = format.getPattern();
final Locale locale = format.hasLocale() ? format.getLocale() : ctxt.getLocale();
DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
if (acceptCaseInsensitiveValues(ctxt, format)) {
builder.parseCaseInsensitive();
}
builder.appendPattern(pattern);
DateTimeFormatter df;
if (locale == null) {
df = builder.toFormatter();
} else {
df = builder.toFormatter(locale);
}

// [#148]: allow strict parsing
if (!deser.isLenient()) {
df = df.withResolverStyle(ResolverStyle.STRICT);
}

// [#69]: For instant serializers/deserializers we need to configure the formatter with
//a time zone picked up from JsonFormat annotation, otherwise serialization might not work
if (format.hasTimeZone()) {
df = df.withZone(format.getTimeZone().toZoneId());
}
deser = deser.withDateFormat(df);
}
if (formatOverrides.hasPattern()) {
final String pattern = formatOverrides.getPattern();
final Locale locale = formatOverrides.hasLocale() ? formatOverrides.getLocale() : ctxt.getLocale();
DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
if (acceptCaseInsensitiveValues(ctxt, formatOverrides)) {
builder.parseCaseInsensitive();
}
// [#58]: For LocalDate deserializers we need to configure the formatter with
//a shape picked up from JsonFormat annotation, to decide if the value is EpochSeconds
JsonFormat.Shape shape = format.getShape();
if (shape != null && shape != _shape) {
deser = deser.withShape(shape);
builder.appendPattern(pattern);
DateTimeFormatter df;
if (locale == null) {
df = builder.toFormatter();
} else {
df = builder.toFormatter(locale);
}
// any use for TimeZone?

// [#148]: allow strict parsing
if (!deser.isLenient()) {
df = df.withResolverStyle(ResolverStyle.STRICT);
}

// [#69]: For instant serializers/deserializers we need to configure the formatter with
//a time zone picked up from JsonFormat annotation, otherwise serialization might not work
if (formatOverrides.hasTimeZone()) {
df = df.withZone(formatOverrides.getTimeZone().toZoneId());
}
deser = deser.withDateFormat(df);
}
// [#58]: For LocalDate deserializers we need to configure the formatter with
//a shape picked up from JsonFormat annotation, to decide if the value is EpochSeconds
JsonFormat.Shape shape = formatOverrides.getShape();
if (shape != null && shape != _shape) {
deser = deser.withShape(shape);
}
// any use for TimeZone?

return deser;
}

private boolean acceptCaseInsensitiveValues(DeserializationContext ctxt, JsonFormat.Value format)
{
Boolean enabled = format.getFeature( Feature.ACCEPT_CASE_INSENSITIVE_VALUES);
Expand Down
6 changes: 6 additions & 0 deletions release-notes/VERSION-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ Modules:
=== Releases ===
------------------------------------------------------------------------

2.12.1 (not yet released)

#196: `@JsonFormat` overriden features don't apply when there are no other
options while deserializing ZonedDateTime
(reported, fix contributed by Maciej D)
2.12.0 (29-Nov-2020)
#94: Deserialization of timestamps with UTC timezone to LocalDateTime
Expand Down

0 comments on commit d475ed1

Please sign in to comment.