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

Gson serialize/deserialize rountrip of java.time.OffsetDateTime drops the time zone component #1526

Closed
tomasaschan opened this issue May 3, 2019 · 4 comments

Comments

@tomasaschan
Copy link

The following snippet illustrates the problem:

final Gson gson = new GsonBuilder().create();
final OffsetDateTime before = OffsetDateTime.now();
System.out.println(String.format("Before:     %s", before));
final String serialized= gson.toJson(before);
System.out.println(String.format("Serialized: %s", serialized));
final OffsetDateTime after = gson.fromJson(serialized, OffsetDateTime.class);
System.out.println(String.format("After:      %s", after));

One run output the following:

Before:     2019-05-03T16:31:25.171+02:00
Serialized: {"dateTime":{"date":{"year":2019,"month":5,"day":3},"time":{"hour":16,"minute":31,"second":25,"nano":171000000}},"offset":{"totalSeconds":7200}}
After:      2019-05-03T16:31:25.171null

Note that on the last line, after the serialization roundtrip, the timezone is dropped. Why? Is this a bug in gson, or a configuration error on my part?

This is with gson 2.8.5 and

>java -version
openjdk version "1.8.0_212"
OpenJDK Runtime Environment (Zulu 8.38.0.13-CA-win64) (build 1.8.0_212-b04)
OpenJDK 64-Bit Server VM (Zulu 8.38.0.13-CA-win64) (build 25.212-b04, mixed mode)
@tomasaschan
Copy link
Author

After doing some research on this, I think I can summarize the root cause:

  • When deserializing a ZoneOffset, gson sets the totalSeconds, but not the id (probably as intended, because id is marked transient)
  • When calling toString on a ZoneOffset, it simply outputs its id
  • When calling toString on an OffsetDateTime, it returns datetime.toString() + offset.toString()

I thus, all the actual information does survive the round-trip, but the redundancy in ZoneOffset is not handled according to the, presumed, intended behavior of the type.

I understand that it's too late to change gson's handling of serializing OffsetDateTime and friends to use eg ISO date strings instead, but IIUC it should be possible to adapt how gson deserializes ZoneOffset specifically, to calculate and set the ID string too (for example, {"totalSeconds": 7200} should have the ID string set to "+02:00").

Is this something that should be done inside gson, or as a plugin? Would a PR with this functionality have any chance of being accepted?

@janos-laszlo
Copy link

janos-laszlo commented Dec 7, 2019

I tried it with a custom TypeAdapter:
https://www.tutorialspoint.com/gson/gson_custom_adapters.htm
and solves this problem in my case

@cesarochoa2006
Copy link

The following snippet illustrates the problem:

final Gson gson = new GsonBuilder().create();
final OffsetDateTime before = OffsetDateTime.now();
System.out.println(String.format("Before:     %s", before));
final String serialized= gson.toJson(before);
System.out.println(String.format("Serialized: %s", serialized));
final OffsetDateTime after = gson.fromJson(serialized, OffsetDateTime.class);
System.out.println(String.format("After:      %s", after));

One run output the following:

Before:     2019-05-03T16:31:25.171+02:00
Serialized: {"dateTime":{"date":{"year":2019,"month":5,"day":3},"time":{"hour":16,"minute":31,"second":25,"nano":171000000}},"offset":{"totalSeconds":7200}}
After:      2019-05-03T16:31:25.171null

Note that on the last line, after the serialization roundtrip, the timezone is dropped. Why? Is this a bug in gson, or a configuration error on my part?

This is with gson 2.8.5 and

>java -version
openjdk version "1.8.0_212"
OpenJDK Runtime Environment (Zulu 8.38.0.13-CA-win64) (build 1.8.0_212-b04)
OpenJDK 64-Bit Server VM (Zulu 8.38.0.13-CA-win64) (build 25.212-b04, mixed mode)

Please check this project. I have found the OffsetDateTime converter of theirs fully working and usefull
https://github.com/aaronweihe/ThreeTen-Backport-Gson-Adapter

@Marcono1234
Copy link
Collaborator

The underlying issue here is that Gson does not have any built-in type adapters for the java.time classes (#1059) and you are (by accident?) relying on reflection-based serialization for these classes. This should be avoided because it makes you dependent on the implementation details of these classes.

As mentioned in the comments above, prefer using a custom type adapter for the class.

@Marcono1234 Marcono1234 closed this as not planned Won't fix, can't repro, duplicate, stale Aug 6, 2022
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

4 participants