FasterXML / jackson-databind

General data-binding package for Jackson (2.x): works on streaming API (core) implementation(s)
Apache License 2.0
3.49k stars 1.37k forks source link

Systemwide property to disable the "Java 8 date/time XYZ not supported by default" error #4533

Open stickfigure opened 2 months ago

stickfigure commented 2 months ago

Is your feature request related to a problem? Please describe.

Jackson 2.12 introduced the "always break when trying to serialize java.time objects without the JavaTimeModule` behavior.

Unfortunately, this breaks our 1M+ line codebase which makes ObjectMappers all over the place. And we have client applications that expect the (terrible) POJO format for some time objects.

It looks like you've already thought about this with your comment here:

https://github.com/FasterXML/jackson-databind/blob/e230f61b05f69cba74f933bd74479b7d764fa9d5/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializerFactory.java#L885

We've pinned jackson to 2.11.4 across the board but this is not a sustainable solution.

Describe the solution you'd like

Ideally, a system property that restores the old behavior - let java.time.* be serialized as objects. A distant second would be a feature to enable on the objectmapper which restores old behavior. That would require hunting down every possible objectmapper creation in our codebase, which will hurt.

Usage example

No response

Additional context

No response

GedMarc commented 2 months ago

Hey @stickfigure , This is actually quite a funny topic as I'm sure you've researched already, which is very tied into the Java version and modular updates,

There may be some other quicker solutions, otherwise I'll definitely take a look at something for java.time

Can I ask which Java base, framework if applied, and library update restrictions you are facing?

pjfanning commented 2 months ago

@stickfigure Have you considered adding a set of centralized methods that create ObjectMappers that work the way that you want? These centralized methods could add a custom serlializer and deserializer that do what you want with java.time instances or even register Jackson's own Java Time module.

There is no so much configurability in Jackson that creating a vanilla ObjectMapper is not likely to suit everyone. For me, there has to be a time where we say that adding yet more configurability so that one user is happy is not a productive use of time. There is now so many configuration options, it is hard to keep track of them all.

It is also an option for you to fork Jackson and do whatever you like to the fork.

stickfigure commented 2 months ago

The problem was discovered going from Spring Boot 2.4 to 2.7, which took Jackson from 2.11 to 2.13. Spring Boot 2.7 seems to be content with Jackson 2.11 but I hesitate to move onto Spring Boot 3.2 with the old version pin. Java is 11 transitioning to 17.

Yes, centralizing ObjectMapper creation would be great but it's 1.4 million lines of code spread over 50 repositories. Not an intractable problem just a painful one.

pjfanning commented 2 months ago

The problem was discovered going from Spring Boot 2.4 to 2.7, which took Jackson from 2.11 to 2.13. Spring Boot 2.7 seems to be content with Jackson 2.11 but I hesitate to move onto Spring Boot 3.2 with the old version pin. Java is 11 transitioning to 17.

Yes, centralizing ObjectMapper creation would be great but it's 1.4 million lines of code spread over 50 repositories. Not an intractable problem just a painful one.

Yes - but it allows you to sort the problem today - instead of waiting for a possible change in Jackson that may not be released for months after the change is made.

pjfanning commented 2 months ago

I have refactored large code bases in the past and it is often significantly less work than originally thought.

If you create a static method like com.example.jackson.JacksonUtil.createObjectMapper() - you can global replace new ObjectMapper() with com.example.jackson.JacksonUtil.createObjectMapper(). This shouldn't take long.

stickfigure commented 2 months ago

Not my first rodeo, and it is of course more complicated than that. I mostly was taking the temperature of whether or not an easy fix might be available; looks the answer is no. We'll deal.

cowtowncoder commented 2 months ago

Correct, I cannot think of an obvious easy solution unfortunately. This issue has come up a few times, and in hindsight I wish I had added a MapperFeature to allow opt-out of blocking Java 8 date/time and Joda serialization failures.

One possible slightly fragile solution would be sub-classing of BeanSerializerFactory and overriding _findUnsupportedTypeSerializer() to not fail on any of libraries, registering with ObjectMapper. ... but then again, requires construction of specifically configured mapper instance so perhaps not worth it.

I vaguely recall someone writing a module for registering POJO serializers that do the "as Object"... but don't have a link handy (assuming I am not just hallucinating :) ).