RosettaCodeData/Task/JSON/C/json.c

121 lines
3.4 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <yajl/yajl_tree.h>
#include <yajl/yajl_gen.h>
static void print_callback (void *ctx, const char *str, size_t len)
{
FILE *f = (FILE *) ctx;
fwrite (str, 1, len, f);
}
static void check_status (yajl_gen_status status)
{
if (status != yajl_gen_status_ok)
{
fprintf (stderr, "yajl_gen_status was %d\n", (int) status);
exit (EXIT_FAILURE);
}
}
static void serialize_value (yajl_gen gen, yajl_val val, int parse_numbers)
{
size_t i;
switch (val->type)
{
case yajl_t_string:
check_status (yajl_gen_string (gen,
(const unsigned char *) val->u.string,
strlen (val->u.string)));
break;
case yajl_t_number:
if (parse_numbers && YAJL_IS_INTEGER (val))
check_status (yajl_gen_integer (gen, YAJL_GET_INTEGER (val)));
else if (parse_numbers && YAJL_IS_DOUBLE (val))
check_status (yajl_gen_double (gen, YAJL_GET_DOUBLE (val)));
else
check_status (yajl_gen_number (gen, YAJL_GET_NUMBER (val),
strlen (YAJL_GET_NUMBER (val))));
break;
case yajl_t_object:
check_status (yajl_gen_map_open (gen));
for (i = 0 ; i < val->u.object.len ; i++)
{
check_status (yajl_gen_string (gen,
(const unsigned char *) val->u.object.keys[i],
strlen (val->u.object.keys[i])));
serialize_value (gen, val->u.object.values[i], parse_numbers);
}
check_status (yajl_gen_map_close (gen));
break;
case yajl_t_array:
check_status (yajl_gen_array_open (gen));
for (i = 0 ; i < val->u.array.len ; i++)
serialize_value (gen, val->u.array.values[i], parse_numbers);
check_status (yajl_gen_array_close (gen));
break;
case yajl_t_true:
check_status (yajl_gen_bool (gen, 1));
break;
case yajl_t_false:
check_status (yajl_gen_bool (gen, 0));
break;
case yajl_t_null:
check_status (yajl_gen_null (gen));
break;
default:
fprintf (stderr, "unexpectedly got type %d\n", (int) val->type);
exit (EXIT_FAILURE);
}
}
static void print_tree (FILE *f, yajl_val tree, int parse_numbers)
{
yajl_gen gen;
gen = yajl_gen_alloc (NULL);
if (! gen)
{
fprintf (stderr, "yajl_gen_alloc failed\n");
exit (EXIT_FAILURE);
}
if (0 == yajl_gen_config (gen, yajl_gen_beautify, 1) ||
0 == yajl_gen_config (gen, yajl_gen_validate_utf8, 1) ||
0 == yajl_gen_config (gen, yajl_gen_print_callback, print_callback, f))
{
fprintf (stderr, "yajl_gen_config failed\n");
exit (EXIT_FAILURE);
}
serialize_value (gen, tree, parse_numbers);
yajl_gen_free (gen);
}
int main (int argc, char **argv)
{
char err_buf[200];
const char *json =
"{\"pi\": 3.14, \"large number\": 123456789123456789123456789, "
"\"an array\": [-1, true, false, null, \"foo\"]}";
yajl_val tree;
tree = yajl_tree_parse (json, err_buf, sizeof (err_buf));
if (! tree)
{
fprintf (stderr, "parsing failed because: %s\n", err_buf);
return EXIT_FAILURE;
}
printf ("Treating numbers as strings...\n");
print_tree (stdout, tree, 0);
printf ("Parsing numbers to long long or double...\n");
print_tree (stdout, tree, 1);
yajl_tree_free (tree);
return EXIT_SUCCESS;
}