-
Notifications
You must be signed in to change notification settings - Fork 117
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 Instant to be serialized as epochSecond without the fraction part #116
Comments
…modules-java8 into issue/FasterXML#116
* test: add initial test case * fix: fix problems in test case for issue #1 * feat: add test cases for timestamps part and nanoseconds part related to issue #1 * create a false test cases #1 * Use flag for diabling fraction * Use flag for diabling fraction * Added the flag for DurationSerializer classes * Removed test cases that are not relevant to the added Serialization Feature * Only keep requirement specific tests Some tests were set up to get an understanding of the code. They should not be kept and included in the pull request Co-authored-by: Nagisa <[email protected]> Co-authored-by: Jacob Adlers <[email protected]>
Thanks for the contribution, taking a look, and also interested in @cowtowncoder 's thoughts on a new flag in SerializationFeature. The nanoseconds handling is one area where there are a few bugs in the issues list. With that in mind, one initial thought on the following:
Given the comment that the Given that, it would be helpful to have a corresponding note in the Anyway, will review this further, thanks again. |
I have some concerns about the new SerializationFeature, but haven't yet been able to formulate exact problem. |
Ok, here are a couple thoughts, I'll add these to the actual code (in the PR) too, but too summarize:
The other thing to still look into is to make sure there aren't any other impacts/changes required, such as in the deserializers? The Travis build ran successfully but that's not always fool-proof. For example, wouldn't there be a corresponding change required in the InstantDeserializer, which is currently assuming nanos or millis? I think a round-trip unit test would validate this, i.e. serialize it out and then deserialize that value..
|
Other things to note:
On (3), this would obviously be bigger change, and there would be challenges regarding merging those settings with already existing alternatives. But it is an option, if (but only if) we managed to define consistent set of date/time configuration options that could work across all date/time types (that is, "classic" JDK |
Yes, I think the Shape.* has helped in a few other cases like this, so that might be a better route. Also, one thing I was thinking about was the case where there are nanoseconds (non-zero), and in the current proposal they'd be lost? That would likely create questions/issues. Now for the |
@kupci If you had time and interest, one possibility would be to maybe write up similar (well, more extensive ideally :) JSTEP entry explaining overall changes to date/time handling. I mean, if you can think of ... maybe collection of ideas, proposals, either for a later 2.x or 3.0. https://github.com/FasterXML/jackson-future-ideas/wiki/JSTEP |
On the But now with EpochSeconds, I don't see a way it would solve this, as both milliseconds and epoch seconds would be And another concerning thing, speaking of defaults and Cowtowncoder's point about the millis default, I just noticed, at least based on the javadoc, the So the However, that looks like a longer effort, I'm working with Jakob on the original changes given these points:
Do you think we should proceed with this route (new SR flag), or fully go with the longer effort towards the |
Right, that whole Time[stamp] Unit for integers (or floats, come to think of that) is my main concern. I create JSTEP placeholder at: https://github.com/FasterXML/jackson-future-ideas/wiki/JSTEP-5 and you should be able to edit it (if not, let me know and I'll figure out access). I added 2 main idea-lets:
I don't think I will accept the PR for 2.11, due to timing and not being convinced it is the way to go -- this gives us some more time to consider good (not perfect) approach, and that can involve longer route. On |
I agree, especially given there's a good (not perfect) workaround for the original issue, where the user is fully in control of determining how to handle the timestamp value (and not getting strange results and maybe writing up issues because they misconfigured a flag):
Thanks to Jakob et al. for highlighting this and helping to generate some thoughts on improvements to the SerializationFeature. |
There are definitely other fixes/enhancement requests that might be addressed by the DateTimeConfig: here's another enhancement request #117
_ |
Created new label to connect these. There is also a databind issue for adding colon in timezone marker on serialization: FasterXML/jackson-databind#1624 something I hoped to get in 2.11, but am worried about compatibility aspects. |
I was hoping there was a better way like those suggested by the original post here. I don't like adding extra getters or annotations to my classes if I can avoid it. As it may be useful to others, to serialize Instant as epoch seconds (with no fractional part), I did the following: private final ObjectWriter objectWriter = new ObjectMapper()
.registerModule(new JavaTimeModule().addSerializer(new EpochSecondInstantSerializer()))
.writerFor(MyValueClass.class); public class EpochSecondInstantSerializer extends JsonSerializer<Instant> {
@Override
public Class<Instant> handledType() {
return Instant.class;
}
@Override
public void serialize(Instant instant, JsonGenerator js, SerializerProvider sp) throws IOException {
js.writeNumber(instant.getEpochSecond());
}
} |
Thanks for including this. This looks like a clean solution, and yes, avoids the impact of extra annotations or SRs that were preventing this from being a simple fix. My thought is that, while certainly there are drawbacks to extending, it is nice to have the capability to extend for situations like this. |
I think it should be epoch millis for this change to be useful. Epoch millis makes the the timestamps portable with regard to both Java and JavaScript; which are the likely producers and consumers on both ends of the request. Default serializer: I currently use this configuration:
This makes the timestamps easily transferrable between the platforms with consistent APIs. Java: long value = 1551461407999L
Instant deserialized = Instant.ofEpochMilli(value)
System.out.println(deserialized)
long serialized = deserialized.toEpochMilli()
System.out.println(serialized)
System.out.println(serialized == value)
System.out.println(Instant.ofEpochMilli(1551461407999L).toEpochMilli() == 1551461407999L) Javascript: var value = 1551461407999;
var deserialized = new Date(value);
console.log(deserialized.toISOString());
var serialized = deserialized.valueOf();
console.log(serialized);
console.log(serialized == value);
console.log(new Date(1551461407999).valueOf() == 1551461407999); Moment.js: var value = 1551461407999;
var deserialized = new moment(value);
console.log(deserialized.toISOString());
var serialized = deserialized.valueOf();
console.log(serialized);
console.log(serialized == value);
console.log(new moment(1551461407999).valueOf() == 1551461407999); All 3 produce:
If some needs/wants epoch seconds, they can use the Instant/Date APIs to truncate to seconds when creating the initial value. |
Couple of notes:
@obarcelonap @kupci WDYT? |
Any update on this topic? |
No updates right now. It looks like there are some good workarounds, and there are folks who don't like adding extra getters or annotations to classes. But otherwise, I could help with
While keeping in mind these requirements:
|
Thanks to all for the helpful thread. I ran into this issue during an update from 2.10.0 -> 2.12.5. 2.10.0: default behaviorfinal Instant instant = Instant.ofEpochSecond(42, 0);
final byte[] bytes = new ObjectMapper().writeValueAsBytes(Map.of("instant", instant));
assertEquals("{\"instant\":{\"epochSecond\":42,\"nano\":0}}", new String(bytes)); 2.12.5: default behaviorfinal Map<String, Object> data = Map.of("instant", Instant.ofEpochSecond(42, 0));
final bytes[] bytes = JsonMapper.builder()
.addModule(new JavaTimeModule())
.build()
.writeValueAsBytes(data);
assertEquals("{\"instant\":42.000000000}", new String(bytes));
// Default behavior results in a decimal without field names. 2.12.5: after disabling
|
@tmancill Glad you found a workaround. One thing I'm curious about is that it looks like, with your scenario, some information was lost, so we'll have to see if that was intentional or an inadvertent change, due to some other change: |
Just wanted to post my solution here, since this was the first thread that came up in a web search and I didn't see an explicit code snippet that solved my problem. I needed to serialize as epoch millisecond without globally configuring the ObjectMapper. This is what solved my use case (I'm working in Kotlin): data class MyPojo(
@JsonFormat(without = [JsonFormat.Feature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS])
val timestamp: Instant
) |
I have an
Instant
field that represents an epoch timestamp in seconds.the mapper is configured this way
However when this gets serialized as
By looking at the code there's no way to serialize this value as epoch seconds using the standard mechanism.
InstantSerializerBase.serialize(T value, JsonGenerator generator, SerializerProvider provider)
The only option is to use :
It could be nice if there could be way to tell jackson to avoid serializing the fraction part.
The text was updated successfully, but these errors were encountered: