HiveBrain v1.2.0
Get Started
← Back to all entries
patterncModerate

Parsing function for a server, using the Jansson library

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
thefunctionparsingusingforlibraryserverjansson

Problem

I'm making a server in C that needs to parse JSON that follows oBIX protocol and I'm using the Jansson library for this. I've been programming in high level languages such as Java and C# for my entire career and the last time I touched C was way back in 7-8 years ago, so I'm mostly looking for guidance on writing C-style code.

Here's a sample JSON input from client to server:

{"obix":"obj","is":"obix:Request","rid":"1","children":[{"obix":"op","name":"add","is":"obix:Watch","children":[{"obix":"obj","is":"obix:WatchIn","children":[{"obix":"list","names":"hrefs","children":[{"obix":"uri","val":"/device/"}]}]}]}]}


So a function I have just needs to validate what kind of request the client is making. First, I write the following defines:

#define OBIX_REQUEST_INVALID -1
#define OBIX_REQUEST_WATCH 0
#define OBIX_REQUEST_UPDATE 1 
....


Then in my callback function. I first validate whether it's a valid JSON input.

int callback_web_socket(struct libwebsocket_context * this,
                                   struct libwebsocket *wsi,
                                   enum libwebsocket_callback_reasons reason,
                                   void *user, void *in, size_t len)
{
    ....

    json_t *root;
    json_error_t error;

    root = json_loads(buf,0,&error);
    if (!root)
    {
         printf("\nInvalid JSON data.\n");
         break;
    }
    ....


If it's valid JSON, I call my parse function to determine request type

int request_type = obix_parse_request(root);
printf("\nRequest Type: %d\n", request_type);


And here's how my parse function looks like:

```
int obix_parse_request(const json_t *obix_root_obj) {
json_t *obix_obj = json_object_get(obix_root_obj,"obix");

if (!json_is_string(obix_obj) || strcmp(json_string_value(obix_obj),"obj") != 0) {
return OBIX_REQUEST_INVALID;
}

json_t *first_child = json_object_get(obix_root_obj, "children");
if (!first_child || !json_is_array(first_child))

Solution

A few notes:

-
My first concern with your program is the use of the Jansson library. Looking at some benchmarks shows me that it is less than stellar. (The Y-axis is parses-per-second. Thus, higher is faster.)

So a new library choice may be in order. I would highly recommend looking a jsmn. I have yet to find a faster (and more portable!) option out there. Here is a benchmark for jsmn compared to Jansson (jsmn is 19.28 times faster).

\$
\newcommand\T{\Rule{0pt}{1em}{.5em}}
\begin{array}{|c|c|c|c|c|c|}
\hline \textbf{Project} & \textbf{License} & \textbf{API} & \textbf{Neg. tests} & \textbf{Followers} & \textbf{Benchmark} \T \\\hline
\text{Jansson} \T & \text{MIT} & \text{DOM} & \text{yes} & \dfrac{234}{59} & 25 \text{MB/s}, 52 \text{s} \\\hline
\text{jsmn} \T & \text{MIT} & \text{custom} & \text{yes} & \dfrac{65}{4} & 482 \text{MB/s}, 2.3 \text{s} \\\hline
\end{array}
\$

-
You have used the preprocessor to define some oBIX request values.

#define OBIX_REQUEST_INVALID -1
#define OBIX_REQUEST_WATCH 0
#define OBIX_REQUEST_UPDATE 1


You could use an enum here instead.

typedef enum 
{
    INVALID = -1,
    WATCH = 0,
    UPDATE = 1
} ObixRequest;


-
You can remove any != 0 tests from your if conditions for maximum C-ness.

-
You sometimes use printf() when you don't have to.

printf("\nInvalid JSON data.\n");


Use puts() for statements like this when you aren't formatting the string. As a plus, you don't have to include the \n characters.

puts("Invalid JSON data.");

Code Snippets

#define OBIX_REQUEST_INVALID -1
#define OBIX_REQUEST_WATCH 0
#define OBIX_REQUEST_UPDATE 1
typedef enum 
{
    INVALID = -1,
    WATCH = 0,
    UPDATE = 1
} ObixRequest;
printf("\nInvalid JSON data.\n");
puts("Invalid JSON data.");

Context

StackExchange Code Review Q#33873, answer score: 10

Revisions (0)

No revisions yet.