GNOME Bugzilla – Bug 660795
Can't get double from integer
Last modified: 2012-10-25 17:20:38 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.
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
(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.
> 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...
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.
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.
[Fixing Default QA assignee for json-glib - see 613232#c1. Sorry for bugmail noise.]
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?
(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.
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.
(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.