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

Add JsonNode.canConvertToExactIntegral() to indicate whether floating-point/BigDecimal values could be converted to integers losslessly #2885

Closed
oguzhanunlu opened this issue Oct 14, 2020 · 10 comments
Labels
hacktoberfest Issue related to Hactoberfest activities, eligible for additional rewards
Milestone

Comments

@oguzhanunlu
Copy link

oguzhanunlu commented Oct 14, 2020

Is your feature request related to a problem? Please describe.
DecimalNode might contain a valid integer or long, however DecimalNode.isIntegralNumber doesn't cover such cases and return false from parent JsonNode.isIntegralNumber .

Describe the solution you'd like
Implement DecimalNode.isIntegralNumber to return true if the value can fit into Long or Int

Usage example
DecimalNode.isIntegralNumber(-1) == true

Additional context
I want to use this check during json schema validation so that e.g. a DecimalNode containing an integer smaller than maximum long value can be considered as integer during type validation where schema has integer as type of the property

@oguzhanunlu oguzhanunlu added the to-evaluate Issue that has been received but not yet evaluated label Oct 14, 2020
@cowtowncoder
Copy link
Member

Hmmh. No, I don't think that would be good idea, changing semantics in a minor version.

However, there is canConvertToInt() and canConvertToLong() -- would these work?

@cowtowncoder cowtowncoder removed the to-evaluate Issue that has been received but not yet evaluated label Oct 14, 2020
@oguzhanunlu
Copy link
Author

oguzhanunlu commented Oct 15, 2020

would these work?

Well, sort of, integral check can be accomplished by combining canConvertToLong and another predicate checking if the value has fractional part, since I don't want to interpret e.g. 12.88 as integral, even though it fits into a Long, so that'll do it.

Thanks for the quick reply and feel free to ping me if you'd like a PR for the next major release.

@cowtowncoder
Copy link
Member

Ah, yes, checking for missing fractional part is sort of orthogonal, so those methods do not quite match what you are trying to do.

So it might be request for yet-another accessor (hasFractionalPart() or something). I am not sure if there are practical challenges wrt double/float backed nodes (it's trivial for BigDecimal as that is 10-based, not 2-based).

@oguzhanunlu
Copy link
Author

so those methods do not quite match what you are trying to do

Yes that's the case and everyone who needs to check fraction will re-implement the same fractional check logic downstream.

An accessor like hasFractionalPart wouldn't change semantics and would come handy for sure, do you think it could be evaluated for a future minor release?

@cowtowncoder
Copy link
Member

@oguzhanunlu Sure: I'll change the title and mark this as potentially good first issue for someone to consider implementing; and it could go in a new minor version (2.12 if contribution came quickly enough; 2.13 otherwise).

@cowtowncoder cowtowncoder changed the title Implement DecimalNode.isIntegralNumber Add something like JsonNode.hasFractionalPart() to indicate whether floating-point/BigDecimal values could be converted to integers losslessly Oct 16, 2020
@cowtowncoder cowtowncoder added 2.12 good first issue Issue that seems easy to resolve and is likely a good candidate for contributors new to project hacktoberfest Issue related to Hactoberfest activities, eligible for additional rewards labels Oct 16, 2020
@bmsbharathi
Copy link

Hi
Can I work on this?

siavashsoleymani pushed a commit to siavashsoleymani/jackson-databind that referenced this issue Oct 17, 2020
@cowtowncoder
Copy link
Member

@bmsbharathi sorry for the slow response: looks like @siavashsoleymani has unfortunately already contributed a PR.

@cowtowncoder
Copy link
Member

Ok, so, I think PR being worked on has functionality that will work on FloatNode / DoubleNode / DecimalNode; we can relatively efficiently check for necessary condition.

But now I wonder about naming of the method. Mostly since there's now the question of what to return in cases of:

  1. Non-floating-point node? They don't really have fractions ever (so that kind of works)
  2. FP value that is "not-a-number" (like positive/negative infinity, or NaN from division by zero) -- does not really have a fraction either -- but in most cases you would NOT want to try conversions from, say, +Infinity.

so since the intent is usually not to check for existence of fraction as much as whether node is losslessly convertible to integral value, this might lead to awkward checks since

I wonder should we not instead name method like:

  • canConvertToIntegralValue() -- true for existing integer types, plus real FP values without fractional part, but false for non-numbers
  • representsIntegralValue() / containsIntegralValue() -- same

or if we stick with check for fractions, switch it to instead use negation

  • hasNoFractionalPart()

because then we could return true for integer nodes, as well as non-numeric things.
It may seem like minor difference (and some would think using negation in method name is a no-no), but I think it all comes down to what is most workable approach wrt actual expected usage.

WDYT?

siavashsoleymani pushed a commit to siavashsoleymani/jackson-databind that referenced this issue Oct 19, 2020
siavashsoleymani pushed a commit to siavashsoleymani/jackson-databind that referenced this issue Oct 19, 2020
siavashsoleymani pushed a commit to siavashsoleymani/jackson-databind that referenced this issue Oct 19, 2020
siavashsoleymani pushed a commit to siavashsoleymani/jackson-databind that referenced this issue Oct 19, 2020
cowtowncoder pushed a commit that referenced this issue Oct 20, 2020
#2885: Add JsonNode.hasFractionalPart()

Co-authored-by: siavashsoleymani <[email protected]>
@cowtowncoder
Copy link
Member

Initial PR merged; will now ponder renaming -- leaning towards changing to something more like isOrConvertibleToIntegral(), which would return true if:

  1. Natively integral numbers: JsonNode.isIntegralNumber() returns true
  2. Coercible from something for which JsonNode.isNumber() returns true (in practice same as if JsonNode.isFloatingPointNumber() returns true)

@cowtowncoder cowtowncoder changed the title Add something like JsonNode.hasFractionalPart() to indicate whether floating-point/BigDecimal values could be converted to integers losslessly Add JsonNode.canConvertToExactIntegral() to indicate whether floating-point/BigDecimal values could be converted to integers losslessly Oct 20, 2020
@cowtowncoder cowtowncoder removed 2.13 good first issue Issue that seems easy to resolve and is likely a good candidate for contributors new to project labels Oct 20, 2020
@cowtowncoder
Copy link
Member

As per title, my current thinking is that method to add will be named

canConvertToExactIntegral()

and will next check that version. But can still consider even better naming until 2.12.0-rc2.

@cowtowncoder cowtowncoder added this to the 2.12.0-rc2 milestone Oct 24, 2020
cowtowncoder added a commit that referenced this issue Oct 24, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
hacktoberfest Issue related to Hactoberfest activities, eligible for additional rewards
Projects
None yet
Development

No branches or pull requests

3 participants