basic/json_parser/parse_example3.c
See examples/basic/json-parser
/*
* ZentriOS SDK LICENSE AGREEMENT | Zentri.com, 2015.
*
* Use of source code and/or libraries contained in the ZentriOS SDK is
* subject to the Zentri Operating System SDK license agreement and
* applicable open source license agreements.
*
*/
#include "zos.h"
typedef struct
{
uint32_t handle;
zos_bool_t keep_next_token;
zos_bool_t in_from_object;
} parse_context_t;
static zos_result_t json_token_callback(void *user, json_parse_context_t *json_context, json_tok_t *tok);
/*************************************************************************************************
* Demonstrates how to read a JSON file in chunks only keeping certain tokens
*/
{
zos_result_t result;
json_parse_context_t *json_context = NULL;
char buffer[128];
parse_context_t parse_context;
{
.buffer = buffer,
.buffer_len = sizeof(buffer),
.reader = file_reader,
.token_callback = json_token_callback
};
memset(&parse_context, 0, sizeof(parse_context));
{
ZOS_LOG("Failed to open: %s", filename);
}
{
ZOS_LOG("Failed to initialize json parsing context");
}
{
ZOS_LOG("Failed to parse json file");
}
else
{
ZOS_LOG("Name/messages:");
{
if(tok->next == NULL)
{
ZOS_LOG("Malformed JSON");
break;
}
const char *name = tok->data.str;
const char *message = tok->next->data.str;
tok = tok->next->next; // skip ahead two tokens
ZOS_LOG(" %s : %s", name, message);
}
}
zn_file_close(parse_context.handle);
json_parse_context_deinit(json_context);
ZOS_LOG("Finished");
return result;
}
/*************************************************************************************************
* This is called before a token is allocated. If this return ZOS_SUCCESS the token is allocated,
* if it returns ZOS_ABORT the token is not allocated, returning anything else will cause the
* parsing to fail.
*/
static zos_result_t json_token_callback(void *user, json_parse_context_t *json_context, json_tok_t *tok)
{
parse_context_t *context = (parse_context_t*)user;
// we want to only keep the 'name' and 'message' VALUES.
if(context->keep_next_token)
{
// the previous token was a 'name' or 'message' key, so keep its value by returning ZOS_SUCCESS
context->keep_next_token = ZOS_FALSE;
}
// is this a string token?
{
// are we entering the 'from' object?
{
context->in_from_object = ZOS_TRUE;
}
// if we're in the 'from' object and
// this is a key 'named' then we want to keep the NEXT token
{
context->in_from_object = ZOS_FALSE;
context->keep_next_token = ZOS_TRUE;
}
// else if this is a 'message' token then we want to keep the next token
{
context->keep_next_token = ZOS_TRUE;
}
}
}
/*************************************************************************************************
* The parser will call this until it returns an error or
* the 'bytes_read' parameter is return with a 0 value.
*/
{
zos_result_t result = ZOS_SUCCESS;
parse_context_t *context = (parse_context_t*)user;
uint32_t has_more_data;
zn_file_poll(context->handle, &has_more_data);
if(has_more_data == 0)
{
// no more data so set this to 0 to tell the parser to stop calling this reader
*bytes_read = 0;
}
{
}
return result;
}