Has Java driver date serialization changed from number/long to ISO string?

I upgraded by Java driver from 3.12.6 to 4.5.0 and there appears to be a difference in how dates are serialized. Previously, serialization would result in a long/number value:

   "entryDate": {
      "$date": 1646317760029
   }

After upgrading to 4.5.0, dates are serialized as an ISO string:

   "entryDate": {
      "$date": "2022-03-03T14:29:20.029Z"
   }

This is an issue when marshaling the JSON into a Java object that expects a long. What’s changed, and how can I can back the old functionality?

1 Like

Hi @John_Manko,

Can you provide some sample code that reproduces the issue? There are multiple API entry points for JSON creation in 3.12.

Thanks,
Jeff

Sure. This code hasn’t changed between driver versions. I have a service that reads from Mongo, converts BSON to a Java JSON, does some manipulation, a returns to a caller. The caller then takes that JSON to does what it needs to do, such as stuff it into a Java-specific object. It’s the bson.toJson() that used to serialize dates as number, but now it’s ISO strings.

    public static javax.json.JsonObject convertDocumentToJson(org.bson.Document bson) throws NullPointerException {
        JsonObject obj = null;
        if(bson == null){
            return obj;
        }
        try (java.io.StringReader sReader = new java.io.StringReader(bson.toJson());
                javax.json.JsonReader reader = javax.json.Json.createReader(sReader)) {
            obj = reader.readObject();
        }
        return obj;
    }

Adding a converter could work, but of course the result json differs:

        JsonWriterSettings settings = JsonWriterSettings.builder()
                .outputMode(JsonMode.EXTENDED)
                .dateTimeConverter((value, writer) -> writer.writeNumber(value.toString()))
                .build();

        try (StringReader sReader = new StringReader(bson.toJson(settings));
{
   "entryDate":1647457718815
}

Which differs from

   "entryDate": {
      "$date": 1647457718815
   }

That’s a breaking change.

Changing JsonMode to STRICT works, but that option is deprecated.

        JsonWriterSettings settings = JsonWriterSettings.builder()
                .outputMode(JsonMode.STRICT)
                .build();

In looking at the documentation, it says:

Strict Mode: Legacy representation. Though now deprecated, this is still the default mode when writing JSON in order to avoid breaking backwards compatibility. This may change in a future major release of the driver.

That’s obviously not true, because the default (no JsonWriterSettings supplied to the toJson() method) clearly behaves differently from supplying .outputMode(JsonMode.STRICT) .

Either the documentation is wrong, or there is a bug in the driver.

The documentation is wrong. 4.0 was the major release in which we changed the default, but clearly we missed some of the places where the 3.x behavior is still documented.

Looks like the API docs are all updated, but not some of the reference docs. The breaking change is also mentioned in the 4.0 Upgrading Guide, as well.

Regards,
Jeff

1 Like

Is this the Upgrade Guide you’re referring to?

Yes , the fourth bullet. It would be better if it mentioned exactly how to revert to the previous behavior.

2 Likes

Yeah, it’s not helpful at all.

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.