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

Deserialize Duration from int-like String (e.g. "3600") #232

Open
jakub-bochenski opened this issue Dec 9, 2021 · 5 comments
Open

Deserialize Duration from int-like String (e.g. "3600") #232

jakub-bochenski opened this issue Dec 9, 2021 · 5 comments
Labels

Comments

@jakub-bochenski
Copy link

jakub-bochenski commented Dec 9, 2021

I think even after #184 and related changes this is still not possible.

Trying to parse a string "3600" into a Duration field results in an exception: "Text cannot be parsed to a Duration"

I've tried adding @JsonFormat("SECONDS") but it seems this only applies to numeric input.

This behaviour is inconsistent with other parts of Jackson:

  • I can convert a int-like String to a regular Long, Integer etc.
  • I can convert a int-like String (e.g. "not_before": "1442340812") to an Instant,
  • I cannot convert an int-like String (e.g. "expires_in": "3600") to a Duration

It would be nice if the handling for @JsonFormat also applied to int-like Strings, not only to actual Numbers

@jakub-bochenski
Copy link
Author

PS. I came across this because there is a certain OAuth provider that does not conform to the rfc an sends the expires_in attribute as a string.

@kupci
Copy link
Member

kupci commented Dec 9, 2021

Thanks, though from a quick look at the code, looks like this should work. Therefore adding the 'test-needed', can be added to the "failing" package for now. Perhaps there's a config flag that needs to be set?

@kupci
Copy link
Member

kupci commented Dec 10, 2021

Ok, I think I see the issue now.. an int-like String isn't supported, since the code directly uses the Duration.parse method, and the parse method uses a special format:

Obtains a Duration from a text string such as PnDTnHnMn.nS.
In other words, something like this:

"PT20.345S" -- parses as "20.345 seconds"

Therefore, there are actually checks in place to ensure the JsonFormat is ignored in this case.

So double minus points on the OAuth provider for not specifying the proper Duration format, per the specification:

"The formats accepted are based on the ISO-8601 duration format PnDTnHnMn.nS with days considered to be exactly 24 hours. "

Therefore, an argument could be made that the OAuth provider needs to fix their code, IMO.

All that said, I don't see why the JsonFormat could not be used, in the cases where there is (1) an int-like String (i.e. no characters, no P prefix) (2) a JsonFormat telling what the int-like String is, just as there is for an actual int. CC @cowtowncoder

@cowtowncoder
Copy link
Member

Unfortunately @JsonFormat and shapes really refer to physical type of JSON value: JSON String that "looks like a number" is still a String, not number: there is no format for "stringified numbers".
So there is no Shape to indicate such cases.

This does not mean that Durations could not be deserializers from such values but... I am not sure this is a good idea for general use. Perhaps this is one case where fully custom deserializers would make sense?
Alternatively I guess simply having a new configuration option for DurationDeserializer would make sense, for indicating that "stringified numbers" are accepted same as JSON integers?

@cowtowncoder
Copy link
Member

FWTW, newly (2.16) added JavaTimeFeature is a mechanism for adding simple on/off flags, one of which could allow enabling behavior suggested here. Something like:

JavaTimeFeature.ALLOW_STRINGIFIED_DURATION_VALUES

enabling of which would allow interpretation of "stringified" numbers as suggested.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants