boostorg / json

A C++11 library for parsing and serializing JSON to and from a DOM container in memory.
https://boost.org/libs/json
Boost Software License 1.0
434 stars 97 forks source link

Can't get_double for a int value in json? #648

Closed kilasuelika closed 3 years ago

kilasuelika commented 3 years ago

For a json like:

{
 "x": 5
}

After read it, then convert it to a double will result in exception:

json["x"].as_double(); //exception
json["x"].get_double(); //no exception, but incorrect value

The problem is that when read a json file. 0 and other integer will default to be integer type in boost.json. There is no way to get them as double except first convert to int and then cast to double. But it's tedious as there may be many values need read.

kilasuelika commented 3 years ago

Use

value_to<double>(json["x"]);

is correct.

vinniefalco commented 3 years ago

Or you can use value::to_number<double>(): https://www.boost.org/doc/libs/develop/libs/json/doc/html/json/ref/boost__json__value/to_number/overload2.html e.g.

json::value jv = 3.0;

int i = jv.to_number< int >();
teathinker commented 10 months ago

this is really an unexpected behavior and should be fixed instead of closed.

grisumbras commented 10 months ago

get_double and as_double give a double if it's stored there, not if it the stored value is convertible to double. This is documented. It wouldn't even make sense to do the conversion, since both return a reference. For as_double there is even an additional note (https://www.boost.org/doc/libs/1_84_0/libs/json/doc/html/json/ref/boost__json__value/as_double/overload2.html), that what you expected to happen will not happen, and is not supposed to happen, because the function has a different purpose. It also mentions that the function you want is value::to_number, which @vinniefalco has suggested above. This is not a bug, this is the intended behaviour, and it is documented.

If value::to_number for some reason does not work for you, please explain why.

teathinker commented 9 months ago

get_double and as_double give a double if it's stored there, not if it the stored value is convertible to double. This is documented. It wouldn't even make sense to do the conversion, since both return a reference. For as_double there is even an additional note (https://www.boost.org/doc/libs/1_84_0/libs/json/doc/html/json/ref/boost__json__value/as_double/overload2.html), that what you expected to happen will not happen, and is not supposed to happen, because the function has a different purpose. It also mentions that the function you want is value::to_number, which @vinniefalco has suggested above. This is not a bug, this is the intended behaviour, and it is documented.

If value::to_number for some reason does not work for you, please explain why.

Thanks for the explanation. I totally understand if it's defined this way, as mentioned in doc. What I was trying to say, was that usually people treated int as a parsable value to double. Checking if a value has decimal or not isn't a typical feature of a parsing library. Maybe using a name like as_decimal_double() make the exception more expected. Thanks.