json-generator_to_data output value is wrong

1 Question

I added double type value “4.01” to json-glib member, but json_generator_to_data() printed “4.0099999999999998”.

root = json_node_new (JSON_NODE_OBJECT);

object = json_object_new ();

 

double version = 4.01;            // Set 4.01 double value

json_object_set_double_member(object, "double", version);

 

json_node_take_object (root, object);

json_generator_set_root (generator, root);

 

g_object_set (generator, "pretty", FALSE, NULL);

data = json_generator_to_data (generator, &len);

 

printf("%s\n",data);              // output : “{"double":4.0099999999999998}”


2 Answer

Json-glib convert double type to string type using the following function to avoid numeric precision problems: 

g_ascii_formatd (buffer, buf_len, "%.17g", d);

Click here to learn more about this function.

For the third argument, the printf() “%.17g” format is used:

  • ‘g’ specifies that the a number in decimal floating point or scientific notation would be represented in their shortest form. For example, 392.65 or 3.9265e+2 would be represented as 392.65.
  • ‘.17’ specifies the precision. This means that a maximum of 17 significant digits will be printed.

Therefore "%.17g" represents the gdouble ‘d’ as a shortest form decimal floating point or scientific notation number to a maximum of 17 significant digits. 

Click here to understand "%.17g" further and learn about printf() formats.

To deal with this this, the

json_object_get_double_member() function can be used. It returnsed the expected right value "4.01" by using the serialized string “{"double":4.0099999999999998}”. See the below code to understand how to do this:

//============= serialize

GError *error = NULL;

JsonNode *node;

JsonParser *parser = json_parser_new ();

parser = json_parser_new ();

json_parser_load_from_data (parser, data, -1, &error);

node = json_parser_get_root (parser);

 

object = json_node_get_object (node);

double dVal = json_object_get_double_member (object, "double");

 

printf("Return : %lf\n",dVal);           // output : “Return : 4.010000”

For sending/receiving data between application, this is no problem.
To create human readable files, use the json_object_set_string_member() function.

 

 

Reference

https://bugzilla.gnome.org/show_bug.cgi?id=672143