Skip to content
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

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

Closed
cowtowncoder opened this issue Feb 5, 2013 · 21 comments

Comments

@cowtowncoder
Copy link
Member

(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.


@beamerblvd
Copy link
Member

Joda does not support java.text.DateFormat (more accurately, java.text.DateFormat does not support Joda types). Likewise, you cannot use java.text.DateFormat with the new Java 8 Date & Time API (it has its own, new date formatter). Because of this, jackson-datatype-joda and jackson-datatype-jsr310 cannot use the date format set by calling ObjectMapper#setDateFromat().

Personally, I would argue for deprecating setDateFormat, noting in the documentation that it does not apply to Joda and JSR-310 data types, and removing it entirely in Jackson 3. In my opinion, if you're serializing dates as strings and you're not using the ISO8601 format, you're not doing it right. I have never heard a compelling argument for using anything other than ISO8601. That date format is supported by SQL Server, Oracle, MySQL, PostgresSQL, HSQL, Java, JavaScript, C#, C++, VB, PHP, Perl, and even bash (bash!), and is the standard format for XML data types. The presence of a setDateFormat method on ObjectMapper is confusing because it implies that all data types can use it, when in actuality they cannot.

@beamerblvd
Copy link
Member

That list of languages/frameworks/servers supporting ISO8601 is not exhaustive. The simple answer is "I have never heard of any language, framework, or database server that did not support ISO8601."

@cowtowncoder
Copy link
Member Author

You might be surprised by number of users who use exotic/eccentric/insane formatting for date values...
I don't think it makes sense to use such exotic notations (damn PHP), but the need seems to exist.

I do realize challenges in supporting generic facility that is based on DateFormat, but I think it serves some value, at least with JDK types. It would be acceptable to have different handling for Joda and new Java8 Date types; for example to:

  1. Ignore DateFormat setting altogether, or
  2. Only use DateFormat if it's of custom date (that is, assume that use of StdDateFormat means that default ISO-8601 variant is used)

At any rate, I think this would warrant more discussion on user and/or dev lists.

@endryha
Copy link

endryha commented Jun 15, 2013

Maybe a simple solution would be to make JodaModule configurable, let's say pass org.joda.time.format.DateTimeFormat in constructor and then use it for all or specific serializers/deserializers?

@cowtowncoder
Copy link
Member Author

Sounds good to me. Would give more power as well.

@idcmp
Copy link

idcmp commented Aug 1, 2013

Is the suggest @endryha proposes in a branch anywhere? It seems like it wouldn't be too onerous to implement and is something I could personally use. Would this (and a bump to depend on joda-time 2.2) be enough to promote a new maven release of this project?

If it's not in progress, it's likely something I could tackle.

@cowtowncoder
Copy link
Member Author

I have not done changes, but it'd be doable for 2.3 version of the module. Module version is synchronized to core components, so we do build a new one for every update. And right now master branch is for 2.3 (2.3.0-SNAPSHOT), where we can make backwards-incompatible changes and API additions.

@cowtowncoder
Copy link
Member Author

Oh and my not working on this is not related to its merits, but my own workload. So I would be happy to see this get implemented, with simple configurability as suggested.

idcmp pushed a commit to idcmp/jackson-datatype-joda that referenced this issue Aug 2, 2013
…dule

- JodaDeserializerBase and JodaSerializerBase gain additional constructor to pass in a joda DateTimeFormatter
- JodaModule constructor accepts a DateTimeFormatter, no-args constructor builds one which uses ISODateTimeFormat
(should be backwards compat)
 - JodaTestBase now has a jodaMapper() method which accepts a DateTimeFormatter
@idcmp
Copy link

idcmp commented Aug 2, 2013

I've done an initial cut at this just for DateTime, you can see the diff here: https://github.com/idcmp/jackson-datatype-joda/compare

My code settings expand out wildcard imports, if this is a problem I can fix that.

If this is generally good, I'll flesh it out for the rest of the data types and create a pull request.

@chadselph
Copy link

Any reason this is getting held up? The diff looks very reasonable and it seems to implement exactly the consensus but there's been no movement in a month.

@cowtowncoder
Copy link
Member Author

I didn't see a pull request. @idcmp can you just create a pull request and I can merge that easily, and it would make it in 2.3.

@ChinaXing
Copy link

+1 hope the dateTimeFormat can be configurable

@cowtowncoder
Copy link
Member Author

I resolved other open low-hanging fruits (for 2.3.1): still hoping for a pull request to include in 2.4.

Joda-specific formatters should be possible to pass via JodaModule; may need two: one for DateTime, other for Period.

@pimlottc
Copy link

As an alternative/complimentary approach, how about allowing use of the @jsonformat annotation to specify patterns based on Joda DateTimeFormat syntax?

@cowtowncoder
Copy link
Member Author

@pimlottc I like that idea! I think it should be ok, since it should not conflict with other kinds of values (like JDK default Date/Time types). Can anyone think of a downside here? This seems like very much textbook use case for this annotation.

@vpratfr
Copy link

vpratfr commented Jul 15, 2014

I'd need configurable date/time/datetime format too. The pull request with the configurable module looks like what I would need, except that there should be 3 instances for formatters : one for time, one for date and one for datetime.

@eyce9000
Copy link

I see that custom formats are supported for serialization using the @jsonformat pattern parameter. Is there any reason that it is not similarly supported for deserialization?

I am having an issue where I want to round-trip an esoteric date format, but it fails in deserialization because of this.

@cowtowncoder
Copy link
Member Author

@eyce9000 No fundamental philosophic reason, just needs to be added in specific handlers.

@watsoncj
Copy link

We found that replacing the serializer on the module for the appropriate types was sufficient.

package my.rad.app;

import com.ecovate.xml.XSDateTimeConverter;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.joda.JodaModule;
import org.joda.time.DateTime;

import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.IOException;

@Configuration
public class JsonProviderConfig {
  @Bean(name="jacksonJaxbJsonProvider")
  public JacksonJsonProvider jsonProvider() {
    JacksonJaxbJsonProvider provider = new JacksonJaxbJsonProvider();
    return configure(provider);
  }

  private <P extends JacksonJsonProvider> P configure(P provider) {
    provider.setMapper(objectMapper());
    return provider;
  }

  private ObjectMapper objectMapper() {
    return new ObjectMapper()
      .registerModule(new JodaModule().addSerializer(DateTime.class, new AnotherDateTimeSerializer()))
      .enable(SerializationFeature.WRAP_ROOT_VALUE)
      .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
  }

  private class AnotherDateTimeSerializer extends com.fasterxml.jackson.databind.JsonSerializer<DateTime> {
    @Override
    public void serialize(DateTime value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
      jgen.writeSt5ring(DateTimeFrmat.forPattern(DateFormat.STRICT_FORMAT))
    }
  }
}

@cowtowncoder
Copy link
Member Author

One additional note for anyone who could help with a patch here: 2.5 has better access to "raw" Pattern value (as String), so it should be quite easy to plug in support. Earlier versions had some minor speed bumps with access.

@cowtowncoder
Copy link
Member Author

Some aspects should now work via "configOverrides" of databind, which allows definition of per-type @JsonFormat defaults.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants