google / gson

A Java serialization/deserialization library to convert Java Objects into JSON and back
Apache License 2.0
23.13k stars 4.27k forks source link

Add fall-back support for "timeless" java.util.Date deserialization in DefaultDateTypeAdapter #2669

Open MuffinTheMan opened 2 months ago

MuffinTheMan commented 2 months ago

Purpose

Adds support for a deserialization scenario where a "timeless" java.util.Date was serialized like "Jan 1, 1970" (Gson's default behavior) but cannot then be deserialized. It seems to make sense that Gson's deserializer should be able to handle deserializing what it serialized itself by default.

Description

This example demonstrates the issue:

@Test
void testSqlDateToUtilDate() throws SQLException {
    try (
        Connection c = ConnectionFactory.getConnection();
        Statement stmt = c.createStatement();
        ResultSet rs = stmt.executeQuery("SELECT '1970-01-01';")
    ) {
        rs.next();
        // rs::getDate() returns java.sql.Date, but that *is a* java.util.Date
        final java.util.Date date = rs.getDate(1);
        final Gson gson = new Gson();
        // This will fail without the fix, because it's serialized as "Jan 1, 1970" but unable
        // to be deserialized from that format. Since adding support for this is trivial, it
        // seems worthwhile. 👇
        assertThat(gson.fromJson(gson.toJson(date), java.util.Date.class)).isEqualTo(date);

        // On the other hand, this does work; however the declared type of `date` is `java.util.Date`,
        // so it would be helpful if it could be deserialized with that same class. The "realistic" scenario
        // is that you have a java.util.Date field on a class that is being populated from a DATE database
        // column (ie using `ResultSet::getDate()` like above); if the class is serialized/deserialized, it
        // will fail deserialization without this fix. 👇
        assertThat(gson.fromJson(gson.toJson(date), java.sql.Date.class)).isEqualTo(date);
    }
}
google-cla[bot] commented 2 months ago

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

Marcono1234 commented 2 months ago

@eamonnmcmanus, do you think we should add the java.sql.Date pattern (new SimpleDateFormat("MMM d, yyyy")) as fallback for deserialization to DefaultDateTypeAdapter? Similar / instead of what is proposed currently by this pull request, see discussion above.

That pattern would then have to be enabled always, even if SqlTypesSupport.SUPPORTS_SQL_TYPES is false, in case users start relying on this pattern for deserialization even when not using java.sql.Date, to avoid failures when those users run on a JDK without SQL types.