Skip to content

JMESPath functions floor and ceil return integer#688

Draft
BartelNieuwenhuyse wants to merge 5 commits intodanielaparker:masterfrom
BartelNieuwenhuyse:bugfix/jmespath_floor-and-ceil-return-integer
Draft

JMESPath functions floor and ceil return integer#688
BartelNieuwenhuyse wants to merge 5 commits intodanielaparker:masterfrom
BartelNieuwenhuyse:bugfix/jmespath_floor-and-ceil-return-integer

Conversation

@BartelNieuwenhuyse
Copy link

JMESPath function floor and ceil return a json float number, while the specs and the examples in it suggest that an integer should be returned.

Expected:
floor(`3.7`) -> 3
Actual:
floor(`3.7`) -> 3.0

case json_type::float64:
{
return *context.create_json(std::ceil(arg0.template as<double>()));
return *context.create_json(static_cast<int64_t>(std::ceil(arg0.template as<double>())));
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way to cast to the underlying type of json_type::int64 instead of to int64_t?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the int64/uint64 case, instead of

return *context.create_json(arg0);

you can safely return arg0.

For the float64 case, you should

  • check if the double value is nan or inf using std::finite, and if so, set ec to jmespath_errc::invalid_type and return null.
  • check if the return value of std::ceil/std::floor is inside the range of an int64_t before doing the cast, and if it isn't, I would suggest leaving it as a double (the alternative would be to convert it to a typename Json::string_type and return it as a Json string value with a sementic_tag::bigint tag)

Regarding,

Is there a way to cast to the underlying type of json_type::int64 instead of to int64_t?

there isn't, but the underlying type is always int64_t.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if defining the numbers is an option, but I seem to hit warnings in my other attempts to define the largest\smallest double that can be safely converted to int64_t.

@danielaparker
Copy link
Owner

danielaparker commented Mar 18, 2026

The cases that fail are failing because a double doesn't have enough precision to represent std::numeric_limits<int64_t>::max() exactly. The upper bound for preserving precision exactly is std::pow(2, std::numeric_limits<double>::digits). Numbers above that limit should remain in double representation. double values above that bound can't be sensibly cast to int types.

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

Successfully merging this pull request may close these issues.

2 participants