This parser has 2 modes: read-only and read-write, which will be refered to respectively as ro
and rw
Warning
This parser does not sanitize the content it reads (for now, at least). Use at your own risk.
To build the program, first clone it from GitHub :
git clone https://github.com/Aeldit/JsonParser.git
Then, enter the following commands
./configure
make json-parser
./json-parser <your_json_file.json>
The configure script accepts the following options :
S
: Runs the script with the-fsanitize=address
gcc flag (checks for memory leaks)D
: Displays some debug informationsSD
orDS
: Use both options
Base rules :
all
: compiles and runs the program inro
mode with the filet.json
rw
: same asall
but inrw
mode (the main file isrw_main.c
)json-parser
: Compiles the project inro
modeclean
: removes the executable
Valgrind rules :
valgrind-compile
: compiles the parser with the-DVALGRING_DISABLE_PRINT
flag (disables the printing functions to only have the time of the parsing functions when using a profiler)valgrind
: callsvalgrind-compile
and generates a callgrind file usable by theKCachegrind
profiling softwareleaks
: checks for leaks but using valgrind (using the filet.json
)
You can change some defines directly at compilation time, depending on your use of this parser
Defines the maximum size of the allocated buffer that is used to store the file (defaults to 2 << 30
, which is roughly equals to 1GB)
Defines the maximum number of nested arrays (defaults to UINT_FAST8_MAX
)
If you want to change this, you can use the following additional flag
-DMAX_NESTED_ARRAYS=<your_value>
Defines the maximum number of nested dict objects (defaults to UINT_FAST8_MAX
)
If you want to change this, you can use the following additional flags
-DMAX_NESTED_DICTS=<your_value>
If you want to use this parser in your C code, put the source and header files of this project in yours :
The third line is to rename the directory
cp -r JsonParser/src/ <your_code_directory>
cd <your_code_directory>
mv src/ json-parser/
Notice how each struct (json, array, dict, value, item) or the parse function is prefixed with
ro
. For read-write mode, they will be prefixed byrw
To read a json file in ro
mode, call the ro_parse()
function :
ro_json_t *j = ro_parse(file_path);
// Once you have this ro_json_t struct pointer, you first have to check whether it is an array or a dict :
if (IS_ARRAY(j))
{
ro_array_ *a = j->array;
// Do stuff with the array
}
else if (IS_DICT(j))
{
ro_dict_t *d = j->dict;
// Do stuff with the dict
}
The arrays contains ro_value_t
elements, while the dicts contain ro_item_t
elements :
Also note the usage of
string_t
, it is a simple typedef struct
ro_value_t | ro_item_t | string_t |
---|---|---|
typedef struct
{
char type;
union
{
string_t strv;
int intv;
double doublev;
char boolv;
ro_array_t *arrayv;
ro_dict_t *dictv;
};
} ro_value_t; |
typedef struct
{
char type;
string_t key;
union
{
string_t strv;
int intv;
double doublev;
char boolv;
ro_array_t *arrayv;
ro_dict_t *dictv;
};
} ro_item_t; |
typedef struct
{
char *str;
unsigned length;
} string_t; |
To access the elements of the array or dict :
// For arrays
ro_value_t v = array_get(a, index);
// For dicts
ro_item_t it = dict_get(d, key);
// The rest is the same for both, except that the arrays don't have keys
if (v.type == T_ERROR)
{
// Handle error
}
// Next we have to check what the type of the value is :
switch (v.type)
{
case T_STR:
// Do stuff with string
break;
case T_INT:
// Do stuff with integer
break;
case T_DOUBLE:
// Do stuff with double
break;
case T_BOOL:
// Do stuff with boolean
break;
case T_NULL:
// Do stuff with null
break;
case T_ARR:
// Do stuff with array
break;
case T_DICT:
// Do stuff with dict
break;
}