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

OffsetTimeSerializer not writing seconds for time object like 15:30:00Z (where seconds is 00) #299

Open
marceloverdijk opened this issue Jan 19, 2024 · 2 comments

Comments

@marceloverdijk
Copy link

marceloverdijk commented Jan 19, 2024

When having a OffsetTime field with e.g. 15:00:00Z and serializing this with Jackson it outputs:
15:00Z and thus the seconds are lost.

Note I have the time module registered via JavaTimeModule().

Although one could argue that the seconds are not needed this gives some problems when validating outputted data against JSON schema.
when using the JSON schema format time then the seconds are expected, see https://json-schema.org/understanding-json-schema/reference/string#dates-and-times
without the seconds the JSON schema validator fails with: The value must be a valid time.
(note I'm using Justify for schema validation)

Looking at the source code, I see this is done on purpose
https://github.com/FasterXML/jackson-modules-java8/blob/master/datetime/src/main/java/tools/jackson/datatype/jsr310/ser/OffsetTimeSerializer.java#L92-L111

    private final void _serializeAsArrayContents(OffsetTime value, JsonGenerator g,
            SerializerProvider provider)
        throws JacksonException
    {
        g.writeNumber(value.getHour());
        g.writeNumber(value.getMinute());
        final int secs = value.getSecond();
        final int nanos = value.getNano();
        if ((secs > 0) || (nanos > 0)) {
            g.writeNumber(secs);
            if (nanos > 0) {
                if(useNanoseconds(provider)) {
                    g.writeNumber(nanos);
                } else {
                    g.writeNumber(value.get(ChronoField.MILLI_OF_SECOND));
                }
            }
        }
        g.writeString(value.getOffset().toString());
    }

Is it possible to override this behaviour?

Currently I think my only option is create a custom Serializer?

If not possible to override this behaviour would it be at least possible to change this _serializeAsArrayContents method from private to protected so one could simply extend this class and override this method?

@marceloverdijk marceloverdijk changed the title OffsetTimeSerializer not writing seconds for time like 15:30:00Z (where seconds is 00) OffsetTimeSerializer not writing seconds for time object like 15:30:00Z (where seconds is 00) Jan 19, 2024
@marceloverdijk
Copy link
Author

Hmm, JSR310FormattedSerializerBase (which the OffsetTimeSerializer extends) is also package protected. So just making that method protected would not help unfortunately.

@cowtowncoder
Copy link
Member

I would not be against relaxing visibility rules where necessary, fwtw (PRs welcome). But sounds like that might not work.

Aside from that, yes, it seems like we could use more configurability. In many cases we could use one of properties of @JsonFormat (which allows use both via annotation itself, and with "ConfigOverrides" which allows specifying JsonFormat.Value for given type) -- but I don't think that'd have suitable option here.

Which would leave 2 further options:

  1. Adding direct configurability to OffsetTimeSerializer -- probably simple setter method (instead of passing in constructor). Not super elegant but would work
  2. Addition of new JavaTimeFeature option (this was added in Jackson 2.16). One challenge is that ideally these settings should be relevant for more than one Date/Time value type. If similar "always include seconds" (... and how about Nanos?) needs exist for other value types, I think this would be the way to go.

I can't guarantee having time to work on this, but I always try to find time to help others if you wanted to try a PR.
Wrt versioning, new functionality should go in 2.17 branch, but I could allow "dark launch" for safe enough features for 2.16 (2.16.2) since 2.17.0 won't be released for months.

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

2 participants