Code Monkey home page Code Monkey logo

jackson-datatype-joda's Introduction

Jackson module (jar) to support JSON serialization and deserialization of Joda data types.

Status

Build Status Maven Central Javadoc

Module has been production-ready since version 2.0, and offers relatively extensive support for Joda datatypes. Contributions are always welcome -- not all types are yet supported; and we may want to support even wider alternative formats on input side.

License

Apache License 2.0

Usage

Since this module extends basic Jackson databind functionality, you may want to check out documentation at Jackson-docs first.

Maven dependency

To use module on Maven-based projects, use following dependency:

<dependency>
  <groupId>com.fasterxml.jackson.datatype</groupId>
  <artifactId>jackson-datatype-joda</artifactId>
  <version>2.17.1</version>
</dependency>    

(or whatever version is most up-to-date at the moment)

Registering module

To use Joda datatypes with Jackson, you will first need to register the module first (same as with all Jackson datatype modules):

ObjectMapper mapper = JsonMapper.builder().addModule(new JodaModule()).build();

Using older style (that is being phased out):

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JodaModule());

Reading and Writing Joda types

After registering Joda module, Jackson Databind will be able to write values of supported Joda types as JSON (and other formats Jackson supports), and read Joda values from same formats.

With JSON, for example, following would work

public class Bean {
  public DateTime start;
}

final String INPUT_JSON = "{\"start\" : \"1972-12-28T12:00:01.000Z\"}";
Bean bean = mapper.readValue(INPUT_JSON, Bean.class);

and property start of Bean would have expected DateTime value.

Conversely, you can produce JSON (and other supported formats) simply with:

String json = mapper.writeValueAsString(bean);
Assert.assertEquals(INPUT_JSON, json);

Compatibility

Module works with Joda version 2.9 and higher (CI tests compatibility since module version 2.14), even if it declares dependency to a newer version. This means that it is possible to use with older version by using Maven dependency override.

More

See Wiki for more information (javadocs, downloads).

jackson-datatype-joda's People

Contributors

arturdryomov avatar beamerblvd avatar chanjarster avatar clamothe avatar cowtowncoder avatar cstivers78 avatar dependabot[bot] avatar devdevx avatar dlvenable avatar ebourg avatar edwardbetts avatar ginkel avatar harmfulbreeze avatar hgschmie avatar joschi avatar joxertmd avatar jwijgerd avatar kyje avatar lorcan avatar mveitas avatar ncjones avatar nezda avatar pjfanning avatar prb avatar rgilles avatar sbtourist avatar stephanepaulus avatar tatu-at-salesforce avatar valery1707 avatar ziobermichal avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jackson-datatype-joda's Issues

Calling JodaDateSerializerBase#isEmpty results in a StackOverflowError

JodaDateSerializerBase#isEmpty(T value) calls JsonSerializer#isEmpty(null, value) which calls #isEmpty(value) again, resulting in a StackOverflowError.

jackson-databind calls isEmpty when serializing various values if the object mapper is configured with mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);.

For example, the serialization of a bean with a non-null field value results in a JsonMappingException wrapping the StackOverflowError.

2.0.0 registers deserializers incorrectly: Object gets coerced to Period

Looks like registration of deserializers is broken for version 2.0.0 (as reported by Pierre). This is because 'isAssignableFrom' tests are incorrect, and basically will use Joda types whenever possible, which means that Object would be mapped (since, say, Period is an Object). Need to change so this will not happen.

Default DateTime parser format is stricter than previous versions, causing incompatibility

In this commit, for DateTimeSerializer:
cf2f4c2#diff-86756f80e06fe3b0a847c963534b14baR55

DateTime.parse() is replaced by using the JacksonJodaDateFormat, which defaults to FormatConfig.DEFAULT_DATETIME_FORMAT, which is defined as new JacksonJodaDateFormat(ISODateTimeFormat.dateTime().withZoneUTC()).

DateTime.parse() uses ISODateTimeFormat.dateTimeParser().withOffsetParsed():
http://www.joda.org/joda-time/apidocs/org/joda/time/DateTime.html#parse-java.lang.String-

So ultimately, the default date time parser format has changed from ISODateTimeFormat.dateTimeParser() to ISODateTimeFormat.dateTime(). Although similar, ISODateTimeFormat.dateTimeParser() is much less restrictive:
http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime--
http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTimeParser--

As an example, the datetime "2015-07-27T08:11:07-07:00" is missing the .SSS milliseconds value, so it fails in 2.6.0 but works in 2.5.4:

Caused by: java.lang.IllegalArgumentException: Invalid format: "2015-07-27T08:11:07-07:00" is malformed at "-07:00"
    at org.joda.time.format.DateTimeFormatter.parseDateTime(DateTimeFormatter.java:899) ~[joda-time-2.8.1.jar:2.8.1]
    at com.fasterxml.jackson.datatype.joda.deser.DateTimeDeserializer.deserialize(DateTimeDeserializer.java:90) ~[jackson-datatype-joda-2.6.0.jar:2.6.0]
    at com.fasterxml.jackson.datatype.joda.deser.DateTimeDeserializer.deserialize(DateTimeDeserializer.java:22) ~[jackson-datatype-joda-2.6.0.jar:2.6.0]
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:520) ~[jackson-databind-2.6.0.jar:2.6.0]
    at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:101) ~[jackson-databind-2.6.0.jar:2.6.0]
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:256) ~[jackson-databind-2.6.0.jar:2.6.0]

A workaround in this situation is to add a @JsonFormat annotation to the property specifying the specific format, e.g: @JsonFormat(pattern="yyyy-MM-dd'T'HH:mm:ssZZ")

DateTimeSerializer should take the configured time zone into account

At the moment the com.fasterxml.jackson.datatype.joda.ser.DateTimeSerializer writes the following code if the WRITE_DATES_AS_TIMESTAMPS feature is disabled:
...
jgen.writeString(value.toString());
...
whereas value is the DateTime object. However this doesn't take the configured timezone into account which might be set in ObjectMapper.setTimeZone(TimeZone timeZone).

A similar Issue was fixed for the DateTimeDeserializer see: #14

Allow definition of default `DateTimeFormatter` (and date-, time-) for module

(migrated from http://jira.codehaus.org/browse/JACKSON-422 reported by Paul Carey)


If WRITE_DATES_AS_TIMESTAMPS is false, the serializer in org.codehaus.jackson.map.ser.StdSerializerProvider#defaultSerializeDateValue
writes a string based on the configured formatter

gen.writeString(_dateFormat.format(date));

In contrast, the corresponding serializer for Joda dates (org.codehaus.jackson.map.ext.JodaSerializers - DateTimeSerializer#serialize)
simply invokes

gen.writeString(value.toString());

The Joda serializer should serialize according to any formatter set on the serialization config.


Failing to map correctly formatted input string

I'm getting the following using Jackson 2.3 with the jodatime module registered in the object mapper:

JsonMappingException: Can not instantiate value of type [simple type, class org.joda.time.DateTime] from String value ('2013-08-28T00:00:00.950Z'); no single-String constructor/factory method (through reference chain: foo.bar.model.impl.MutableItem["created"])

Adjust LocalDate / LocalDateTime deserializer to support `DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE`

When deserializing from a long, UTC should be specified to be in keeping with

http://wiki.fasterxml.com/JacksonFAQDateHandling

  • Jackson defaults to GMT/UTC ("How come this time is off by 9 hours?")

To be even more flexible, the DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE feature I wasn't aware of could be mapped from and utilized here too.

Looks like similar approach to #29 would work https://github.com/FasterXML/jackson-datatype-joda/blob/master/src/main/java/com/fasterxml/jackson/datatype/joda/deser/LocalDateDeserializer.java#L40

I'm currently "working around" this with DateTimeZone.setDefault(DateTimeZone.UTC); but this is problematic.

Test case: timestamp 1238544000000L in my timezone is 3/31/2009 but 4/1/2009 in UTC

@Test
  public void aprilFools() {
    final long aprilFools = 1238544000000L;
    System.err.println("date "+new LocalDate(aprilFools));
    System.err.println("UTC date "+new LocalDate(aprilFools, DateTimeZone.UTC));
  }

SerializationFeature.WRITE_DATES_WITH_ZONE_ID writes inconsistent Zone Offset

With SerializationFeature.WRITE_DATES_WITH_ZONE_ID turned on I get serialized dates like "1970-01-01T00:00:00.000Z[Europe/London]" instead of the expected "1970-01-01T00:00:00.000+01:00[Europe/London]".

jackson-datatype-jsr310 module seems to serialize it correctly.

Unit test:

public void testWriteDatesWithZoneId() throws Exception
{
    ObjectWriter w = MAPPER.writer();

    w = w.with(SerializationFeature.WRITE_DATES_WITH_ZONE_ID);

    assertEquals(quote("1970-01-01T00:00:00.000+01:00[Europe/London]"),
            w.without(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
                    .writeValueAsString(DATE_JAN_1_1970_EUROPE_LONDON));
}

Can't deserialize a serialized DateTimeZone with default typing

Trying to serialize a DateTimeZone instance, then deserialize it back afterwards; it always fails. Looks like it's due to the fact that there is no type mapping for CachedDateTimeZone (indeed for any of the subclasses of DateTimeZone) and no String constructor, combined with our project's use of default typing on serialized objects.

package com.rw;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.joda.JodaModule;
import org.joda.time.DateTimeZone;
import org.junit.Assert;
import org.junit.Test;

public class TestTimeZone {

    @Test
    public void testTimeZoneSerialization() throws Exception {
        final ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

        objectMapper.registerModule(new JodaModule());

        final DateTimeZone timeZone = DateTimeZone.forID("America/New_York");
        final String json = objectMapper.writeValueAsString(timeZone);

        final DateTimeZone timeZoneRead = objectMapper.readValue(json, DateTimeZone.class);

        Assert.assertNotNull(timeZoneRead.getID());
        Assert.assertEquals("America/New_York", timeZoneRead.getID());
    }
}

Result:

com.fasterxml.jackson.databind.JsonMappingException: Can not instantiate value of type [simple type, class org.joda.time.tz.CachedDateTimeZone] from String value ('America/New_York'); no single-String constructor/factory method
 at [Source: ["org.joda.time.tz.CachedDateTimeZone","America/New_York"]; line: 1, column: 40]

Obviously, a simple workaround is to create a mix-in just for DateTimeZone that disables typing only for it. The following test passes:

package com.rw;

import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.joda.JodaModule;
import org.joda.time.DateTimeZone;
import org.junit.Assert;
import org.junit.Test;

public class TestTimeZone {

    @Test
    public void testTimeZoneSerialization() throws Exception {
        final ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        objectMapper.addMixIn(DateTimeZone.class, DateTimeZoneMixin.class);

        objectMapper.registerModule(new JodaModule());

        final DateTimeZone timeZone = DateTimeZone.forID("America/New_York");
        final String json = objectMapper.writeValueAsString(timeZone);

        final DateTimeZone timeZoneRead = objectMapper.readValue(json, DateTimeZone.class);

        Assert.assertNotNull(timeZoneRead.getID());
        Assert.assertEquals("America/New_York", timeZoneRead.getID());
    }

    @JsonTypeInfo(use = JsonTypeInfo.Id.NONE)
    public interface DateTimeZoneMixin {

    }
}

Release 2.3.2

Would it be possible to do a release to match up with Jackson 2.3.2?

Inconsistent LocalDate format (instead of using array, allow numeric timestamp too)

I recently ran across this for LocalDate:

    if (provider.isEnabled(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)) {
        // Timestamp here actually means an array of values
        jgen.writeStartArray();

This doesn't make sense to me. A timestamp is a well-defined thing and is not an array.

This can obviously be improved, but how to do it? Thoughts on one of the options below? My preference is #1 but I don't know if the array thing is useful to anyone.

  1. Make WRITE_DATES_AS_TIMESTAMPS actually write a timestamp. Eliminate the array-writing behavior.
  2. Do 1, but add a new option called WRITE_LOCALDATE_AS_ARRAY in case someone cares about this behavior and wants to opt-in.
  3. Add a new option for DONT_WRITE_LOCALDATE_AS_ARRAY that makes WRITE_DATES_AS_TIMESTAMPS behave as expected. Most compatible, least clean, requires future users of this to discover the special setting to get expected behavior.

ะกustom date format is deserialized incorrectly

Here my code snapshot:

public class DateTimeTest {
    private static final String DATE_PATTERN = "yyyyMMdd";

    public static DateTime date = DateTime.now();

    public static void main(String[] args) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new JodaModule());
        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        ObjectWriter writer = mapper.writer();

        String str = writer.writeValueAsString(new Domain());
        System.out.println(str);

        ObjectReader reader = mapper.reader(Domain.class);
        Domain domain = reader.readValue(str);

        System.out.println(domain.getDate());
    }

    private static class Domain {
        @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = DATE_PATTERN)
        private DateTime date;

        public Domain() {
            this.date = DateTime.now();
        }

        public DateTime getDate() {
            return date;
        }

        public void setDate(DateTime date) {
            this.date = date;
        }
    }
}

I'm expecting to serialize and deserialize objects back and force. But for some strange reason the result of code execution is

{"date":"20151117"}
20151117-01-01T00:00:00.000Z

During deserialization the year of the date becomes 20151117. That is definitely wrong.

If I change date pattern to "dd/MM/yyyy", then I even start getting error "IllegalArgumentException: Invalid format". So for sure Jackson ignores date pattern for deserialization.

ObjectMapper.can(De)Serialize(โ€ฆ, AtomicReference<Throwable>) does not catch all exceptions

The overloads for ObjectMapper.can(De)Serialize(โ€ฆ) were introduced in 2.3 to allow clients to find out why the mapper might be incapable of (de)serializing a type. However, internals sometimes throw exceptions that are not properly captured in the AtomicReference. For example POJOPropertyBuilder.findRenamed(โ€ฆ) throws an IllegalStateException that will propagate out of can(De)Serialize(โ€ฆ).

WRITE_DATES_WITH_ZONE_ID feature not working when applied on @JsonFormat annotation

Copied over from FasterXML/jackson-databind#1175 as was assigned to wrong module.

Firstly thank you for a fantastic library :-) Just one small issue:-

I am using Jackson 2.7.3 and I would like to specify the date format pattern and whether or not to display timezone information on a per property basis. Therefore I have specified

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss", with = JsonFormat.Feature.WRITE_DATES_WITH_ZONE_ID)

on my date property - see example class below:-

private static class DummyClassWithDate {
        @JsonProperty("name")
        private String name;
        @JsonProperty("age")
        private int age;
        @JsonProperty("date")
        @JsonFormat
                (shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss Z", with = JsonFormat.Feature.WRITE_DATES_WITH_ZONE_ID)
        private DateTime date;

        public DummyClassWithDate() {

        }

        public DummyClassWithDate(String name, int age, DateTime date) {
            this.name = name;
            this.age = age;
            this.date = date;
        }

        public String getName() {
            return name;
        }

        public int getAge() {
            return age;
        }

        public DateTime getDate() {
            return date;
        }

        public void setName(String aName) {
            name = aName;
        }

        public void setAge(int anAge) {
            age = anAge;
        }

        public void setDate(DateTime aDate) {
            date = aDate;
        }

    }

However, although the pattern is being used, the timezone is not being preserved when serialized. Here is a unit test which shows the problem:

    private final DummyClassWithDate dummyClassWithDateIncludingTimezone = new DummyClassWithDate("Test", 50, new DateTime(2015, 11, 23, 22, 06, 39, DateTimeZone.forID("Asia/Krasnoyarsk")));

    @Test
    public void testJacksonAnnotatedPOJOWithDateWithTimezoneToJson() throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new JodaModule());

        assertEquals("{\"name\":\"Test\",\"age\":50,\"date\":\"23-11-2015 10:06:39 +0800[Asia/Krasnoyarsk]\"}",mapper.writeValueAsString(dummyClassWithDateIncludingTimezone));
    }

and the results of running the test:

junit.framework.ComparisonFailure: 
Expected :{"name":"Test","age":50,"date":"23-11-2015 10:06:39 +0800[Asia/Krasnoyarsk]"}
Actual   :{"name":"Test","age":50,"date":"23-11-2015 02:06:39 +0000"}

If I change my test to add in:

mapper.configure(SerializationFeature.WRITE_DATES_WITH_ZONE_ID, true);
this fixes the issue however this is applying the setting to dates on ALL classes and I really only want it applied to specific properties.

Joda != JodaTime

You might consider renaming this to jackson-datatype-jodaTIME since it does not support the full joda stack, joda-money for example.

Usage example?

There are no usage examples in the docs.

I have no idea how to use the different serialization choices or even what it will look like in the JSON.

Error in ObjectMapperConfig example in wiki

There is an example in the wiki how you can configure the pre-defined object mappers by using a ObjectMapperConfig, but it is slightly broken. Should be:

RestAssured.config = RestAssuredConfig.config().objectMapperConfig(new ObjectMapperConfig().gsonObjectMapperFactory(
        new GsonObjectMapperFactory() {
            public Gson create(Class cls, String charset) {
                return new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
            }
        }
));

Can not deserialize instance of org.joda.time.DateTime or LocalDate out of START_OBJECT token

v2.1.1, joda module.

I can convert a json file to a pojo in a unit test using objectMapper.readValue(file, pojo .class);

However, when a Spring RESTTemplate client invokes the default json converter to convert an inputStream containing the domain object with Joda types (DateTime or LocalDate), it generates an error: objectMapper.readValue(httpInputMessage.getBody(), javaType)

   
com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of org.joda.time.DateTime out of START_OBJECT token
at Source: org.mortbay.jetty.HttpParser$Input@46a09b; line: 1, column: 752
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164)
at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:599)
at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:593)
at com.fasterxml.jackson.datatype.joda.deser.DateTimeDeserializer.deserialize(DateTimeDeserializer.java:51)
at com.fasterxml.jackson.datatype.joda.deser.DateTimeDeserializer.deserialize(DateTimeDeserializer.java:21)
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:375)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:559)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObjectUsingNonDefault(BeanDeserializer.java:393)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:289)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:226)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:203)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:23)
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:375)
at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeSetAndReturn(MethodProperty.java:106)
at com.fasterxml.jackson.databind.deser.BuilderBasedDeserializer.deserializeFromObject(BuilderBasedDeserializer.java:326)
at com.fasterxml.jackson.databind.deser.BuilderBasedDeserializer.deserialize(BuilderBasedDeserializer.java:143)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:226)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:203)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:23)
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:375)
at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeSetAndReturn(MethodProperty.java:106)
at com.fasterxml.jackson.databind.deser.BuilderBasedDeserializer.deserializeFromObject(BuilderBasedDeserializer.java:

Same issue occurs with LocalDate

com.fasterxml.jackson.databind.JsonMappingException: Unexpected token (START_OBJECT), expected START_ARRAY: expected JSON Array, String or Number
at Source: org.mortbay.jetty.HttpParser$Input@d297c0; line: 1, column: 51
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164)
at com.fasterxml.jackson.databind.DeserializationContext.wrongTokenException(DeserializationContext.java:692)
at com.fasterxml.jackson.datatype.joda.deser.LocalDateDeserializer.deserialize(LocalDateDeserializer.java:50)
....

Why is the call chain passing a START_OBJECT in one case and START_ARRAY in the other?

Change in timezone handling for Date created from Joda DateTime between 2.6.2 and 2.6.3

In 2.6.3, I'm seeing a DateTime that's in UTC move into BST (my timezone) when it's converted into a Date and written as a String. In 2.6.1 and 2.6.2 it stays in UTC. This code reproduces the problem:

    public static void main(String[] args) throws JsonProcessingException {
        ObjectMapper objectMapper = createObjectMapper();
        DateTime dateTime = new DateTime(1988, 6, 25, 20, 30, DateTimeZone.UTC);
        System.out.println(objectMapper
                .writeValueAsString(dateTime));
        Date date = dateTime.toDate();
        System.out.println(objectMapper
                .writeValueAsString(date));
    }

    private static ObjectMapper createObjectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(createJodaModule());
        mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss ZZZ"));
        return mapper;
    }

    private static SimpleModule createJodaModule() {
        SimpleModule module = new SimpleModule();
        module.addSerializer(DateTime.class, new DateTimeSerializer(
                new JacksonJodaDateFormat(DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss ZZZ")
                        .withZoneUTC())));
            return module;
    }

The output for various versions of Jackson:

2.6.1

"1988-06-25 20:30:00 UTC"
"1988-06-25 20:30:00 +0000"

2.6.2

"1988-06-25 20:30:00 UTC"
"1988-06-25 20:30:00 +0000"

2.6.3

"1988-06-25 20:30:00 UTC"
"1988-06-25 21:30:00 +0100"

(originally raised by @wilkinsona in FasterXML/jackson-databind#973)

OSGi joda import does not allow joda upgrade

Hi,
We are using a more uptodate version of joda time. And we love to use jackson!
But the current Import-Package header of your jackson-datatype-joda bundle prevent us to upgrade.

Import-Package: ...
 ...
 ...,org.joda.time;version=
 "[2.1.0,2.2)",org.joda.time.format;version="[2.1.0,2.2)"

As you can see your restriction is strong you only support the current minor version: 2.1 and related micros.
At this point of time the latest release from joda time is the 2.3.
Maybe, an option could be to relax your upper bound like this:

Import-Package: ...
 ...
 ...,org.joda.time;version=
 "[2.1.0,3)",org.joda.time.format;version="[2.1.0,3)"

What do you think?

Thanks,

Romain.

Custom deserializer for Joda Interval is not called before the Jackson's own deserializer?

I represent intervals using the following custom format (2014-02-27T00:00:00.999Z~2014-02-28T00:00:00.999Z) in my JSON. I have a custom deserializer that would deserialize this into an Joda Interval. I have a test that verifies that this deserializer works. But when I try to deserialize this in a Spring Controller class, I get the following exception:

java.lang.ClassNotFoundException: org.joda.time.ReadableInstant not found by jackson-mapper-asl

I am pretty sure Joda is in my classpath because there are other DateTime parameters in this controller that gets deserialized. From the stack trace, it just looks like Jackson's looks at the first part of my interval string which looks like a DateTime field and invokes the standard datetime deserializer. But something goes wrong in this process and never calls my custom deserializer. I assumed my custom deserializer would be called before Jackson's own. Is this true? Can someone throw light into this problem.

Here is my JSON:

{
"intervals" : [
"2014-02-27T00:00:00.999Z~2014-02-28T00:00:00.999Z"
]
}

Here is my class:
class MyClass
{
List intervals;

@JsonCreator
public MyClass(
@JsonProperty("intervals")
@JsonDeserialize(contentUsing = MyIntervalDeserializer.class)
@JsonSerialize(contentUsing = MyIntervalSerializer.class)
List intervals)
{ this.intervals = intervals; }
}

Here is the stack trace of the error:

java.lang.ClassNotFoundException: org.joda.time.ReadableInstant not found by jackson-mapper-asl [128]
at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1460)
at org.apache.felix.framework.BundleWiringImpl.access$400(BundleWiringImpl.java:72)
at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:1843)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
at org.codehaus.jackson.map.ext.JodaDeserializers.provide(JodaDeserializers.java:27)
at org.codehaus.jackson.map.ext.OptionalHandlerFactory.findDeserializer(OptionalHandlerFactory.java:117)
at org.codehaus.jackson.map.deser.BasicDeserializerFactory.findStdBeanDeserializer(BasicDeserializerFactory.java:554)
at org.codehaus.jackson.map.deser.BeanDeserializerFactory.createBeanDeserializer(BeanDeserializerFactory.java:573)
at org.codehaus.jackson.map.deser.StdDeserializerProvider._createDeserializer(StdDeserializerProvider.java:432)
at org.codehaus.jackson.map.deser.StdDeserializerProvider._createAndCache2(StdDeserializerProvider.java:341)
at org.codehaus.jackson.map.deser.StdDeserializerProvider._createAndCacheValueDeserializer(StdDeserializerProvider.java:321)
at org.codehaus.jackson.map.deser.StdDeserializerProvider.findValueDeserializer(StdDeserializerProvider.java:167)
at org.codehaus.jackson.map.deser.BasicDeserializerFactory.createCollectionDeserializer(BasicDeserializerFactory.java:274)
at org.codehaus.jackson.map.deser.StdDeserializerProvider._createDeserializer(StdDeserializerProvider.java:420)
at org.codehaus.jackson.map.deser.StdDeserializerProvider._createAndCache2(StdDeserializerProvider.java:341)
at org.codehaus.jackson.map.deser.StdDeserializerProvider._createAndCacheValueDeserializer(StdDeserializerProvider.java:321)
at org.codehaus.jackson.map.deser.StdDeserializerProvider.findValueDeserializer(StdDeserializerProvider.java:167)
at org.codehaus.jackson.map.deser.std.StdDeserializer.findDeserializer(StdDeserializer.java:596)
at org.codehaus.jackson.map.deser.BeanDeserializer.resolve(BeanDeserializer.java:379)
at org.codehaus.jackson.map.deser.StdDeserializerProvider._resolveDeserializer(StdDeserializerProvider.java:438)
at org.codehaus.jackson.map.deser.StdDeserializerProvider._createAndCache2(StdDeserializerProvider.java:383)
at org.codehaus.jackson.map.deser.StdDeserializerProvider._createAndCacheValueDeserializer(StdDeserializerProvider.java:321)
at org.codehaus.jackson.map.deser.StdDeserializerProvider.findValueDeserializer(StdDeserializerProvider.java:167)
at org.codehaus.jackson.map.deser.StdDeserializerProvider.findTypedValueDeserializer(StdDeserializerProvider.java:188)
at org.codehaus.jackson.map.ObjectMapper._findRootDeserializer(ObjectMapper.java:2820)
at org.codehaus.jackson.map.ObjectMapper._readMapAndClose(ObjectMapper.java:2719)
at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1854)

Configured date/time format not considered when serializing Joda Instant

The configured date/time format is not considered for org.joda.time.Instant since version 2.4.4 and newer. In earlier versions Instants were serialized using the configured formatter.

Reproduce with the follwing code snippet:

  @Test
  public void testInstantConversion() throws Exception {
    ObjectMapper om = new ObjectMapper();
    om.registerModule(new JodaModule());

    // Configure Date Formatting
    om.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
    om.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"));

    // Create an instant and serialize and additonally serialize the instant as DateTime to demonstrate the difference
    org.joda.time.Instant now = new Instant();
    String jsonInstant = om.writeValueAsString(now);
    String jsonDateTime = om.writeValueAsString(now.toDateTime());

    // just to show the version that was used when running the demo
    System.out.println("packageVersion: " + com.fasterxml.jackson.datatype.joda.PackageVersion.VERSION);

    System.out.println("jsonInstant: " + jsonInstant);
    System.out.println("jsonDateTime: " + jsonDateTime);

    assertThat(jsonInstant).isEqualTo(jsonDateTime); // will fail for jackson-datatype-joda > 2.4.4
  }

Output using v2.4.3:

packageVersion: 2.4.3
jsonInstant: "2015-05-11T13:40:14.541Z"
jsonDateTime: "2015-05-11T13:40:14.541Z"

Output using v2.4.4:

packageVersion: 2.4.4
jsonInstant: "2015-05-11T13:46:41.081Z"
jsonDateTime: "2015-05-11T13:46:41.081Z"

Output using v2.5.0:

packageVersion: 2.5.0
jsonInstant: 1431352169061
jsonDateTime: "2015-05-11T13:49:29.061Z"

org.junit.ComparisonFailure: 
Expected :'["2015-05-11T13:49:29.061Z"]'
Actual   :'[1431352169061]':

Output using v2.5.3:

packageVersion: 2.5.3
jsonInstant: 1431352294592
jsonDateTime: "2015-05-11T13:51:34.592Z"

org.junit.ComparisonFailure: 
Expected :'["2015-05-11T13:51:34.592Z"]'
Actual   :'[1431352294592]'

TimeZone in DeserializationContext is ignored with SerializationFeature.WRITE_DATES_WITH_ZONE_ID

As discussed in #67, here's a simple test case that reproduces the issue. In #66 SerializationFeature.WRITE_DATES_WITH_ZONE_ID is supported, but the original TimeZone in DeserializationContext is not.

        MAPPER.setTimeZone(TimeZone.getTimeZone("Europe/Paris"));

        Interval interval = MAPPER.readValue(quote("1396439982-1396440001"), Interval.class);
        assertEquals(1396439982, interval.getStartMillis());
        assertEquals(1396440001, interval.getEndMillis());
        assertEquals(ISOChronology.getInstance(DateTimeZone.forID("Europe/Paris")), interval.getChronology());

(2.8?) Apply `withOffsetParsed()` on formats by default

(note: spun from #74)

Looks like it would make sense to call withOffsetParsed() method on date formatters, by default, instead of having to add it depending on settings, unless there are downsides to this.
Hopefully our unit test suite can give some guidance as to any potential issues. Also obviously need to verify what Joda javadocs say about this method.

Make DateTimeDeserializer abide by configured TimeZone

ObjectMapper.setTimeZone(TimeZone timeZone) is used for setting the TimeZone with which date-times are parsed. However, DateTimeDeserializer ignores this setting.

Line 42:

return new DateTime(jp.getLongValue(), DateTimeZone.UTC);

Line 49:

return new DateTime(str, DateTimeZone.UTC);

The resulting date time is always UTC, which is 1) not desirable and 2) not consistent with other deserializers.

I changed line 42 to:

return new DateTime(jp.getLongValue(), DateTimeZone.forTimeZone(ctxt.getTimeZone()));

And line 49 to:

return new DateTime(str, DateTimeZone.forTimeZone(ctxt.getTimeZone()));

And it works just like it's supposed to now.

Please apply this patch to DateTimeDeserializer so that it abides by configured TimeZone. Thanks! :-)

JodaModule creates org.joda.time.DateTime that fails .equals when compared with original

Originally this was FasterXML/jackson-databind#617

I was surprised to find that a org.joda.time.DateTime instance was not .equals to the org.joda.time.DateTime that produced the JSON in the first place.

/**
 * Configure Jackson to do ISO-8601 conversions on DateTimes.
 */
public class JodaThroughJacksonTest {
  static class Beanie {
    public final DateTime jodaDateTime;
    public final Date javaUtilDate;
    @JsonCreator
    public Beanie(@JsonProperty("jodaDateTime") DateTime jodaDateTime,
        @JsonProperty("javaUtilDate") Date javaUtilDate) {
      this.jodaDateTime = jodaDateTime;
      this.javaUtilDate = javaUtilDate;
    }
  }

  @Test
  public void iso8601ThroughJoda() throws ParseException, IOException {
    ObjectMapper mapper = new ObjectMapper();
    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    mapper.registerModule(new JodaModule());
    mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);

    DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss zzz");
    Date targetDate = df.parse("2000-01-01 00:00:00 UTC");
    Beanie expectedBean = new Beanie(new DateTime(targetDate.getTime()), targetDate);

    String expectedJSON =
        "{\"jodaDateTime\":\"2000-01-01T00:00:00.000Z\","
            + "\"javaUtilDate\":\"2000-01-01T00:00:00.000+0000\"}";
    String actualJSON = mapper.writeValueAsString(expectedBean);
    assertEquals(actualJSON, expectedJSON);

    Beanie actualBean = mapper.readValue(actualJSON, Beanie.class);
    assertEquals(actualBean.javaUtilDate, expectedBean.javaUtilDate);
    assertEquals(actualBean.jodaDateTime.getMillis(), expectedBean.jodaDateTime.getMillis());

    /*
     * Why doesn't the JodaModule deserialize a DateTime that is equal to the one it serialized in
     * the first place? I expected these two to be equal but they aren't.
     */
    assertEquals(actualBean.jodaDateTime, expectedBean.jodaDateTime);
  }
}

There is a git repository supported by a gradle build that demonstrates the issue at https://github.com/robertkuhar/jacksonjodawtf

testDateMidnightSerWithTypeInfo test dependent on $TZ

Hi there. I'm running into a problem with the test suite. It doesn't pass unless the $TZ environment variable is set to "GMT":

$ TZ=Australia/Sydney mvn test
-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.fasterxml.jackson.datatype.joda.JodaSerializationTest
Tests run: 17, Failures: 2, Errors: 0, Skipped: 0, Time elapsed: 0.622 sec <<< FAILURE!
Running com.fasterxml.jackson.datatype.joda.JodaMapperTest
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.023 sec
Running com.fasterxml.jackson.datatype.joda.TestVersions
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.003 sec
Running com.fasterxml.jackson.datatype.joda.DateTimeTest
Tests run: 5, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.07 sec
Running com.fasterxml.jackson.datatype.joda.deser.ReadablePeriodDeserializerTest
Tests run: 7, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.037 sec
Running com.fasterxml.jackson.datatype.joda.deser.MiscDeserializationTest
Tests run: 35, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.151 sec
Running com.fasterxml.jackson.datatype.joda.MixedListTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.029 sec

Results :

Failed tests:   testDateMidnightSer(com.fasterxml.jackson.datatype.joda.JodaSerializationTest): null     expected:<"2001-05-2[5]"> but was:<"2001-05-2[4]">
  testDateMidnightSerWithTypeInfo(com.fasterxml.jackson.datatype.joda.JodaSerializationTest): null expected:<...Midnight","2001-05-2[5]"]> but was:<...Midnight","2001-05-2[4]"]>

Tests run: 68, Failures: 2, Errors: 0, Skipped: 0

$ TZ=GMT mvn test
------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.fasterxml.jackson.datatype.joda.JodaSerializationTest
Tests run: 17, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.613 sec
Running com.fasterxml.jackson.datatype.joda.JodaMapperTest
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.018 sec
Running com.fasterxml.jackson.datatype.joda.TestVersions
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.002 sec
Running com.fasterxml.jackson.datatype.joda.DateTimeTest
Tests run: 5, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.064 sec
Running com.fasterxml.jackson.datatype.joda.deser.ReadablePeriodDeserializerTest
Tests run: 7, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.031 sec
Running com.fasterxml.jackson.datatype.joda.deser.MiscDeserializationTest
Tests run: 35, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.147 sec
Running com.fasterxml.jackson.datatype.joda.MixedListTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.028 sec

Results :

Tests run: 68, Failures: 0, Errors: 0, Skipped: 0

Could this be a bug in the code, or just an unexpected external dependency in the test suite?

Regards,

Tim.

Duration should not be tied to SerializationFeature.WRITE_DATES_AS_TIMESTAMPS

Based on issue #24 Durations are now serialized in ISO-8601 format when SerializationFeature.WRITE_DATES_AS_TIMESTAMPS is disabled. I don't believe that this behavior is correct. A Duration does not represent a Date, and should not be tied to WRITE_DATES__AS_TIMESTAMPS. This also makes it impossible to provide a date formatter for writing dates, while writing durations as milliseconds.

compile against joda 2.2

there are changes in interface between 2.1 and 2.2
particularly
java.lang.NoSuchMethodError: org.joda.time.format.DateTimeFormatter.withZoneUTC()
is forcing me to override multiple classes to use this module in my application
if i submitted a pull request that bumps to 2.2 would you pull it in for 2.3.3 release?

Interval deserialization fails for negative start instants

The root cause appears to be that the code detects the hyphen from the negative number as the hyphen separating the two timestamps, causing a failed attempt to parse an empty string into a long.

For example, the following JSON representing a list of Intervals containing a single item

["-9223372036854775808-23"]

results in the following exception and stack trace

java.lang.NumberFormatException: For input string: ""
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
    at java.lang.Long.parseLong(Long.java:431)
    at java.lang.Long.valueOf(Long.java:525)
    at com.fasterxml.jackson.datatype.joda.deser.IntervalDeserializer.deserialize(IntervalDeserializer.java:28)
    at com.fasterxml.jackson.datatype.joda.deser.IntervalDeserializer.deserialize(IntervalDeserializer.java:14)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:230)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:207)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:23)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromArray(BeanDeserializerBase.java:1112)
    ... 32 more

Improper handling of xsi:nil

Joda DateTime deserialization is working well for me, except in the case that the element is nil.

DateTimeDeserializer never hits a VALUE_NUMBER_INT or a VALUE_STRING, so it throws a mapping exception.

Affected version:
com.fasterxml.jackson.datatype:jackson-datatype-joda:2.3.0
With:
com.fasterxml.jackson.datatype:jackson-dataformat-xml:2.3.0

DateTime serialization should preserve the timezone

I guess it has always been like this, but it doesn't make much sense to me. DateTime is basically a LocalDateTime with a DateTimeZone attached. Generally when people are using DateTime they want time zone info, otherwise they would use a LocalDateTime.

I think as a result of this design decision, many people have to implement custom DateTime functionality to deal with time zone.

What jackson should be doing is to write out the time zone id along with the millis for DateTimes.

add iso format support

Hello,
It'd be nice to add an option to format date using the IsoDateTimeFormat, instead of the timestamp value.

JodaSerialization test failures: testDateMidnightSer and testDateMidnightSerWithTypeInfo

I observed two test failures after checking out master and running the tests locally.

Run at 5:45pm on Jan 12, 2015 in Thailand, in a local timezone of GMT+7

Tests run: 15, Failures: 2, Errors: 0, Skipped: 0, Time elapsed: 0.073 sec <<< FAILURE! - in com.fasterxml.jackson.datatype.joda.JodaSerializationTest
testDateMidnightSer(com.fasterxml.jackson.datatype.joda.JodaSerializationTest)  Time elapsed: 0.009 sec  <<< FAILURE!
junit.framework.ComparisonFailure: expected:<"2001-05-2[5]"> but was:<"2001-05-2[4]">
    at junit.framework.Assert.assertEquals(Assert.java:100)
    at junit.framework.Assert.assertEquals(Assert.java:107)
    at junit.framework.TestCase.assertEquals(TestCase.java:269)
    at com.fasterxml.jackson.datatype.joda.JodaSerializationTest.testDateMidnightSer(JodaSerializationTest.java:41)

testDateMidnightSerWithTypeInfo(com.fasterxml.jackson.datatype.joda.JodaSerializationTest)  Time elapsed: 0.009 sec  <<< FAILURE!
junit.framework.ComparisonFailure: expected:<...Midnight","2001-05-2[5]"]> but was:<...Midnight","2001-05-2[4]"]>
    at junit.framework.Assert.assertEquals(Assert.java:100)
    at junit.framework.Assert.assertEquals(Assert.java:107)
    at junit.framework.TestCase.assertEquals(TestCase.java:269)
    at com.fasterxml.jackson.datatype.joda.JodaSerializationTest.testDateMidnightSerWithTypeInfo(JodaSerializationTest.java:56)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.