Euphoria Audio, LLC

Audio, Video and Data Consulting

libJSON Basic Parser Example

3 Comments »

libJSON is a great C/C++ library written by Jonathan Wallace and can be found on Sourceforge. Previously we looked at how to create a new JSON node tree programmatically that could be sent over the wire to consumer. Now we'll look at the consumer side and see how to parse the JSON string into our application.

First we'll look at the main function in our program that will take a JSON string as input, parse it using the library and pass the tree to a function that will extract useful data.

char *json = "{\"RootA\":\"Value in parent node\",\"ChildNode\":{\"ChildA\":\"String Value\",\"ChildB\":42}}";
JSONNODE *n = json_parse(json);
ParseJSON(n);
json_delete(n);

The first line is just a simple JSON string containing a child object from this example. You'll likely get a string from a web service, message buss or even a file.

Line 2 is where the magic happens in the library. We just pass the string to json_parse and if all is well, we'll receive a pointer to a node tree in return. NOTE that the parser is going to allocate memory for the node tree, so you have to free it on your own as we do in line 4.

Line 3 is a function call that we define for iterating through the JSON tree. While mine isn't pretty, it gets the job done for simple JSON objects.

void ParseJSON(JSONNODE *n){
	if (n == NULL || n == JSON_NULL){
		printf("Invalid JSON Node\n");
		return;
	}

	JSONNODE_ITERATOR i = json_begin(n);
	while (i != json_end(n)){
		if (*i == NULL || *i == JSON_NULL){
			printf("Invalid JSON Node\n");
			return;
		}

		// recursively call ourselves to dig deeper into the tree
		if (json_type(*i) == JSON_ARRAY || json_type(*i) == JSON_NODE){
			ParseJSON(*i);
		}

		// get the node name and value as a string
		json_char *node_name = json_name(*i);

		// find out where to store the values
		if (strcmp(node_name, "RootA") == 0){
			json_char *node_value = json_as_string(*i);
			strcpy(rootA, node_value);
			json_free(node_value);
		}
		else if (strcmp(node_name, "ChildA") == 0){
			json_char *node_value = json_as_string(*i);
			strcpy(childA, node_value);
			json_free(node_value);
		}
		else if (strcmp(node_name, "ChildB") == 0)
			childB = json_as_int(*i);

		// cleanup and increment the iterator
		json_free(node_name);
		++i;
	}
}

The first thing you want to do is check for NULL or JSON_NULL (which is just a redefine of an ASCII null character). If at any point in the parsing you run into a NULL value, then its likely that the JSON string wasn't formatted properly.

Next on line 7 we get a pointer to the first iterator of the node we're currently dealing with. The iterator lets us navigate through the child nodes, one by one.

Line 8 begins a while loop that will continue until we've reached the final iterator returned by json_end.

Again, we should check for an invalid iterator in case something went screwey, and we do so on line 9.

If the iterator is currenly pointing to a node of type JSON_ARRAY or JSON_NODE, that means we are at a branch that requires a new iterator for processing. Thus line 16 makes a recursive call to the function so that we can start processing on the child node. Without this call, we would get the name of the node but trying to get a value would return nothing.

On line 20 we call the json_name method that will return a string with the name of the node. If the node is not named or it's an array's value, the string will be empty, so check for that. Also note that you MUST free the memory returned by json_name as we do on line 37.

Lines 23 through 34 are a simple decision tree that attempt to match the name of the node to known values and if a match is made, we use one of the library functions to extract the value of the node. json_as_string naturally returns the value of the node as a string. This is probably the easiest to use in that it doesn't care if the value of the node is encased in quotation marks or not, it will always return a string. You can read any node as a string and then typecast to whatever need.

Lin 37 frees up the node name allocation.

Line 38 increments our iterator to the next node.

So there you have a very simple little parser that will iterate through your tree and grab extract the data. Naturally you'll want to add error handling and tweak it for your own use.

3 Responses

I’m not too sure on using the C++ style as it was easier to just crank out the C code. I assume it would be similar though.

  • what about using c++ style ?

  • Thank you

  • Leave a Reply