Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

parsing JSON with jansson in C

Tags:

json

c

text

web

So I have been working on writing a program in C that can access the API's of various cryptocurrency sites like www.cryptsy.com, I have the cURL portion figured out and gave the program spit out the JSON data into a char* variable which looks like this:

{"success":"1","return":{"balances_available":{"ALF":"0.00000000","AMC":"0.00000000","ADT":"0.00000000","ANC":"0.00000000","ARG":"0.00000000","ASC":"0.00000000","BQC":"0.00000000","BTB":"0.00000000","BTC":"0.00535673","BTG":"0.00000000","CAP":"0.00000000","BTE":"0.00000000","CSC":"0.00000000","CNC":"0.00000000","COL":"0.00000000","CPR":"0.00000000","CLR":"0.00000000","CMC":"0.00000000","CRC":"0.00000000","BUK":"0.00000000","CGB":"0.00000000","Points":"0.00911000","DVC":"0.00000000","DMD":"0.00000000","DGC":"0.00000000","DBL":"0.00000000","ELC":"0.00000000","ELP":"0.00000000","EMD":"0.00000000","EZC":"0.00000000","FST":"0.00000000","FTC":"0.00000000","FLO":"0.00000000","FRK":"0.00000000","FRC":"0.00000000","GLX":"0.00000000","GME":"0.00000000","GLC":"0.00000000","GLD":"0.00000000","GDC":"0.00000000","HBN":"0.00000000","HYC":"0.00000000","IFC":"0.00000000","IXC":"0.00000000","XJO":"0.00000000","JKC":"0.00000000","KGC":"0.00000000","LTC":"0.00000000","LK7":"0.00000000","LKY":"0.00000000","MST":"0.00000000","MEC":"0.00000000","MEM":"0.00000000","MNC":"0.00000000","NMC":"0.00000000","NAN":"0.00000000","NEC":"0.00000000","NET":"0.00000000","NBL":"0.00000000","NRB":"0.00000000","NVC":"0.00000000","ORB":"0.00000000","PYC":"0.00000000","PPC":"0.00000000","CENT":"0.00000000","PHS":"0.00000000","PXC":"0.00000000","XPM":"0.00000000","PTS":"0.00000000","QRK":"0.00000000","RED":"0.00000000","RYC":"0.00000000","SRC":"0.00000000","SXC":"0.00000000","SPT":"0.00000000","SBC":"0.00000000","STR":"0.00000000","TAG":"0.00000000","TEK":"0.00000000","TRC":"0.00000000","TIX":"0.00000000","WDC":"0.00000000","XNC":"0.00000000","YAC":"0.00000000","ZET":"0.00000000"},"balances_hold":{"ALF":"0.00000000","AMC":"0.00000000","ADT":"0.00000000","ANC":"0.00000000","ARG":"0.00000000","ASC":"0.00000000","BQC":"0.00000000","BTB":"0.00000000","BTC":"0.00000000","BTG":"0.00000000","CAP":"0.00000000","BTE":"0.00000000","CSC":"0.00000000","CNC":"0.00000000","COL":"0.00000000","CPR":"0.00000000","CLR":"0.00000000","CMC":"0.00000000","CRC":"0.00000000","BUK":"0.00000000","CGB":"0.00000000","Points":"0.00000000","DVC":"0.00000000","DMD":"0.00000000","DGC":"0.00000000","DBL":"0.00000000","ELC":"0.00000000","ELP":"0.00000000","EMD":"0.00000000","EZC":"0.00000000","FST":"0.00000000","FTC":"0.00000000","FLO":"0.00000000","FRK":"0.00000000","FRC":"0.00000000","GLX":"0.00000000","GME":"0.00000000","GLC":"0.00000000","GLD":"0.00000000","GDC":"0.00000000","HBN":"0.00000000","HYC":"0.00000000","IFC":"0.00000000","IXC":"0.00000000","XJO":"0.00000000","JKC":"0.00000000","KGC":"0.00000000","LTC":"1.10231195","LK7":"0.00000000","LKY":"10.36912507","MST":"0.00000000","MEC":"0.00000000","MEM":"0.00000000","MNC":"0.00000000","NMC":"0.00000000","NAN":"0.00000000","NEC":"0.00000000","NET":"0.00000000","NBL":"0.00000000","NRB":"0.00000000","NVC":"0.00000000","ORB":"0.00000000","PYC":"0.00000000","PPC":"0.00000000","CENT":"0.00000000","PHS":"0.00000000","PXC":"0.00000000","XPM":"0.00000000","PTS":"0.00000000","QRK":"0.00000000","RED":"0.00000000","RYC":"0.00000000","SRC":"0.00000000","SXC":"0.00000000","SPT":"0.00000000","SBC":"0.00000000","STR":"0.00000000","TAG":"0.00000000","TEK":"0.00000000","TRC":"0.83964122","TIX":"0.00000000","WDC":"0.00000000","XNC":"0.00000000","YAC":"0.00000000","ZET":"0.00000000"},"servertimestamp":1387347714,"servertimezone":"EST","serverdatetime":"2013-12-18 01:21:54","openordercount":3}}

which looks like valid JSON data to me so I decided to try to use jansson to do the JSON parsing/decoding, which looks like this in my code:

char *data;

if ( argc < 2 )
{
    fprintf( stderr, "Must provide URL to fetch.\n" );
    return 1;
}
//data = mmpool_api( argv[1] );
data = cryptsy_api( argv[1] );

json_t *root;
json_error_t error;

root = json_loads( data, 0, &error );
if ( !root )
{
    fprintf( stderr, "error: on line %d: %s\n", error.line, error.text );
    return 1;
}
if ( !json_is_array(root) )
{
    fprintf( stderr, "error: root is not an array\n" );
    json_decref(root);
    return 1;
}

for( int i = 0; i < json_array_size(root); i++ )
{
    json_t *data, *success, *returned, *bal_avail;
    const char *balance;

    data = json_array_get( root, i );
    if ( !json_is_object(data) )
    {
        fprintf( stderr, "error: data %d is not an object\n", i + 1 );
        json_decref(root);
        return 1;
    }

    success = json_object_get( data, "success" );
    if ( !json_is_number(success))
    {
        fprintf( stderr, "error: %d: success is not a number", i+1 );
        json_decref(root);
        return 1;
    }

    returned = json_object_get(data, "return" );
    if ( !json_is_object(returned) )
    {
        fprintf( stderr, "error: %d: return is not an object", i+1  );
        json_decref(root);
        return 1;
    }

    bal_avail = json_object_get( returned, "balances_available" );
    if ( !json_is_array( bal_avail ))
    {
        fprintf( stderr, "error: %d: bal_avail is not an array", i+1 );
        json_decref(root);
    }

    balance = json_string_value(bal_avail);
    printf( "%s %.*s\n",
        json_string_value(bal_avail),
        newline_offset(balance),
        balance);
}
json_decref(root);

but the program just fails stating that root is not an array, so it dies on the second if statement after the JSON code starts. I have noticed that jansson has its own "request(url)" function that you can use to make a request to a server for the JSON data but to get the data I am getting you need to send a secret key/API key and hash them with SHA512 to get a valid response, this function does not seem to have the capability.

I know that there are other libraries for C for decoding JSON data but I just wanted to make sure that I am not doing something wrong here before I switched to JSON-C or another library. Thanks

EDIT::

ok so I have tried to change the code to just parse through the 'root' object, but it seems to only go through the "return" and "success" keys.. perhaps I still dont fully understand but here is the code I am using now to try to parse everything, I read the jansson API guide and it says to use an iterator if you want to go over each and every key:value pair in the object like this:

char *data;

if ( argc < 2 )
{
    fprintf( stderr, "Must provide URL to fetch.\n" );
    return 1;
}
//data = mmpool_api( argv[1] );
data = cryptsy_api( argv[1] );

json_t *root;
json_error_t error;

root = json_loads( data, 0, &error );
if ( !root )
{
    fprintf( stderr, "error: on line %d: %s\n", error.line, error.text );
    return 1;
}

const char *key;
json_t *value;

void *iter = json_object_iter( root );
while( iter )
{
    key = json_object_iter_key(iter);
    value = json_object_iter_value(iter);

    printf("Key: %s, Value: %f\n", key, json_real_value(value) );

    iter = json_object_iter_next(root, iter);
}

json_decref(root);

but it comes out like this ( only the first two items are address and they are in reverse order):

Key: return, Value: 0.000000 Key: success, Value: 0.000000

like image 469
Asphyxiated Avatar asked Dec 19 '13 02:12

Asphyxiated


1 Answers

The root element of your JSON string is an object, not an array. Arrays in JSON are denoted with square brackets [ and ], and objects are denoted with curly brackets { and }. You won't need to iterate over the “object” root element if you already know what keys you want to access, just use json_object_get(root, "keyname"); until you have accessed all the values you need.

like image 111
dreamlax Avatar answered Oct 14 '22 08:10

dreamlax