boostorg / boostorg/json

boost::json::value::is_uint64() behaves unintuitively

Open
#984 18 comments 0 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
479
Forks
110
Avg merge
10d 3h
Merged PRs (30d)
5

Description

Currently using Boost 1.83.0

I'm developing a program with boost::json and want to be able to tell if an incoming numeric value is signed or not, and I find the behavior of boost::json::value::is_int64() boost::json::value::is_uint64() and boost::json::value::is_double() to behave in a way that is highly unintuitive.

### Steps necessary to reproduce the problem
Take the simple JSON:
`{ MyVal: 2 }`

2 is a small whole number and could easily be interpreted as int64, uint64, or double without trouble
The JSON specification wisely does not demand that libraries adhere to any default type considerations when parsing and so it is left to the implementation to determine what primitive type the number is.

if one were to parse the json to a value the following would all be true

```
// assume that MyVal is a boost::json::value type corresponding to MyVal above
MyVal.is_int64() == true
Myval.is_uint64() == false
MyVal.is_double() == false
```
And indeed attempting to run the conversions would result in the following:
```
MyVal.as_int64(); // GOOD no except
MyVal.as_uint64(); // exception
MyVal.as_double(); // exception
```
This is inline with boost documentation, but it doesn't make sense to me, using only the information contained within the JSON it is impossible for boost::json to tell exactly what primitive type is actually a best fit for this value. If a developer is ingesting multiple JSONs with this structure as part of an API, and all the valid JSONs are unsigned whole numbers as I am, then when low numbers like this are received exceptions are possible, and the code must be written instead:
```
try
{
unsigned long long int Output = MyVal.to_number();
}
catch (...)
{
// record some error, toss out the JSON, etc.
}
```

I don't see any reason, logically, why for numbers like 2 the method value::is_uint64() should return false instead of true,
or why the conversion value::as_uint64() should throw an exception, except to match the result of value::is_uint64()

This problem appears to be compounded by the fact that the JSON specification does not allow for leading zeros which might otherwise indicate the full scope of a number like this one; notably it does appear to allow for trailing zeros and decimals which could assist with finding doubles.

Would it not be better for ambiguous numbers like these to present true for all type checking methods where the type could accurately represent the value being checked?

### All relevant compiler information
using g++ 13.2.1

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.