After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 660795 - Can't get double from integer
Can't get double from integer
Status: RESOLVED FIXED
Product: json-glib
Classification: Core
Component: Core
0.14.x
Other All
: Normal normal
: ---
Assigned To: json-glib-maint
json-glib-maint
Depends on:
Blocks:
 
 
Reported: 2011-10-03 15:21 UTC by Alexander AB
Modified: 2012-10-25 17:20 UTC
See Also:
GNOME target: ---
GNOME version: ---



Description Alexander AB 2011-10-03 15:21:20 UTC
After parsing, any _get_double function can return 0.

I'm posting a small code to show the problem:


JsonParser *parser = json_parser_new ();
json_parser_load_from_data (parser, "[4.7,3]", -1, NULL);
JsonNode *node = json_parser_get_root (parser);
JsonArray *array = json_node_get_array (node);

g_print ("%f\n", json_array_get_double_element (array, 0)); //says 4.7, which is right
g_print ("%d\n", json_array_get_int_element (array, 1)); //says 3, which is right, too
g_print ("%f\n", json_array_get_double_element (array, 1)); //says 0.00

g_object_unref (parser);


So the problem which the bug causes is, if I _set_double(3) and store it into a file with the generator, I can't _get_double back with the parser.
Comment 1 Daniil Ivanov 2011-10-13 12:27:00 UTC
Note, that your array has 2 elements and json_array_get_*_element returns default value in case you go out of boundaries
http://git.gnome.org/browse/json-glib/tree/json-glib/json-array.c#n259
Comment 2 Alexander AB 2011-10-13 14:00:12 UTC
(In reply to comment #1)
> Note, that your array has 2 elements and json_array_get_*_element returns
> default value in case you go out of boundaries

Right, this is reasonable behavior, but nothing goes out of boundaries in my example.

The problem is in the json_node_get_double function
http://git.gnome.org/browse/json-glib/tree/json-glib/json-node.c#n704

It returns 0.0 if the node type is G_TYPE_DOUBLE and does nothing with an integer value.

It would be great, if it could return value of an integer node. For example like this:

if (G_VALUE_TYPE (&(node->data.value)) == G_TYPE_DOUBLE)
    return g_value_get_double (&(node->data.value));
else if (G_VALUE_TYPE (&(node->data.value)) == G_TYPE_INT64)
    return (gdouble) g_value_get_int64 (&(node->data.value));

or in more sophisticated gvalue way.
Comment 3 Alexander AB 2011-10-13 14:06:22 UTC
> It returns 0.0 if the node type is G_TYPE_DOUBLE and does nothing with an
> integer value.
Sorry! It returns 0.0 if a node type is NOT G_TYPE_DOUBLE...
Comment 4 Daniil Ivanov 2011-10-13 14:20:10 UTC
Sorry, my bad.
But then this is similar behaviour to g_value_get_double
http://git.gnome.org/browse/glib/tree/gobject/gvaluetypes.c#n1018
you get 0 if debug is enabled and value is not double
and some integer casted to double, if debug is not enabled.
Comment 5 Emmanuele Bassi (:ebassi) 2011-10-17 10:19:31 UTC
we can do some type promotion, but there are issues when dealing with GValue type transformation: any client code can inject arbitrary type transformation functions inside GValue, and thus I cannot just use g_value_transform() (which would actually be the right thing, given that the transformation logic would be stable and in sync with GLib's).

I might be able to follow the JavaScript type promotion, so that every int becomes a double, and every double gets truncated to its integer part; obviously there are other concerns with this approach: what happens to strings and null? what happens if you try to get an int or a double with a complex type?

this, incidentally, is the reason why there are a bunch of type checking functions and macros in JSON-GLib.
Comment 6 André Klapper 2012-03-13 22:08:22 UTC
[Fixing Default QA assignee for json-glib - see 613232#c1. Sorry for bugmail noise.]
Comment 7 Jan Schmidt 2012-07-15 07:58:38 UTC
I just ran into this with 0.14.2. It took me a while to figure out that I could send "1.01" as a double, but not "1.0"

What good is json_builder_set_double/json_parser_get_double if it randomly fails on some subset of the values?
Comment 8 Emmanuele Bassi (:ebassi) 2012-07-15 12:43:18 UTC
(In reply to comment #7)
> I just ran into this with 0.14.2. It took me a while to figure out that I could
> send "1.01" as a double, but not "1.0"
> 
> What good is json_builder_set_double/json_parser_get_double if it randomly
> fails on some subset of the values?

it's not "random": JSON is a wire serialization format, it stores *exactly* what you told it to, and JSON-GLib follows that. it's also a non-validated serialization format, which means that your parser has to do validation on what you expect, including the types of data; JSON-GLib provides all the API needed to check type type of a JsonNode.

if you want to send a double, and you call json_node_set_double(1.0) (or one of its wrappers), then the serialization will effectively send the IEEE version of the double precision floating point number you sent - in a locale-independent way, using g_ascii_dtostr(). if you use json_node_set_int(1) (or one of its wrappers) in your generator code, and expect a double in your parser code, then you are doing something wrong in you serialization spec, and the fault does not lie with JSON-GLib.

having said that, JsonNode (and everything that uses it) as of master relaxed the type checking of the typed getter functions for numeric types, and will do an implicit conversion for those - i.e. if you call get_int() and the JsonNode stores a double, you'll get an integer that will follow the same implicit conversion rules as C. i.e. if your generator code uses set_double(42.7) and your parser code uses get_int(), you will get 42, and not 0. this does not happen for strings, objects, and arrays: if your node stores a string, you will get 0; and if your node stores a double, you won't get a string back.
Comment 9 Jan Schmidt 2012-07-15 14:00:42 UTC
Sorry - perhaps I wasn't clear in my complaint.

With 0.14.2, I am using json_builder_set_double(), and json_parser_get_double() - and it fails, returning 0.0 from the parser if the sent value happens to be exactly integral.

If the value passed to json_builder_set_double() happens to be 1.0, then it will serialise as 'value: 1' and fail to be parsed as a double on the receiving end.

My work-around is indeed to check the type of the JsonNode and fetch an integer out of it, it's just annoying to send a double and then have to check what was received.
Comment 10 Emmanuele Bassi (:ebassi) 2012-10-25 17:20:38 UTC
(In reply to comment #9)
> Sorry - perhaps I wasn't clear in my complaint.
> 
> With 0.14.2, I am using json_builder_set_double(), and json_parser_get_double()
> - and it fails, returning 0.0 from the parser if the sent value happens to be
> exactly integral.

this has been fixed in master, as I said in comment 8.