JSON
[Libraries]

The Make Controller JSON library provides a very small and very fast library for parsing and generating json. More...


Data Structures

struct  JsonEncode_State
 The structure used to maintain the state of a JSON encode process. More...
struct  JsonDecode_State
 The structure used to maintain the state of a JSON decode process. More...

Functions

void JsonEncode_Init (JsonEncode_State *state)
 Initialize or reset the state of a JsonEncode_State variable.
char * JsonEncode_ObjectOpen (JsonEncode_State *state, char *buf, int *remaining)
 Open up a new JSON object.
char * JsonEncode_ObjectKey (JsonEncode_State *state, char *buf, const char *key, int *remaining)
 Set the key for a JSON object.
char * JsonEncode_ObjectClose (JsonEncode_State *state, char *buf, int *remaining)
 Close a JSON object.
char * JsonEncode_ArrayOpen (JsonEncode_State *state, char *buf, int *remaining)
 Open up a new JSON array.
char * JsonEncode_ArrayClose (JsonEncode_State *state, char *buf, int *remaining)
 Close an array.
char * JsonEncode_String (JsonEncode_State *state, char *buf, const char *string, int *remaining)
 Add a string to the current JSON string.
char * JsonEncode_Int (JsonEncode_State *state, char *buf, int value, int *remaining)
 Add an int to a JSON string.
char * JsonEncode_Bool (JsonEncode_State *state, char *buf, bool value, int *remaining)
 Add a boolean value to a JSON string.
void JsonDecode_SetIntCallback (bool(*int_callback)(void *ctx, int val))
 Set the function to be called back when an integer is parsed.
void JsonDecode_SetFloatCallback (bool(*float_callback)(void *ctx, float val))
 Set the function to be called back when a float is parsed.
void JsonDecode_SetBoolCallback (bool(*bool_callback)(void *ctx, bool val))
 Set the function to be called back when a boolean is parsed.
void JsonDecode_SetStringCallback (bool(*string_callback)(void *ctx, char *string, int len))
 Set the function to be called back when a string is parsed.
void JsonDecode_SetStartObjCallback (bool(*start_obj_callback)(void *ctx))
 Set the function to be called back when an object is started.
void JsonDecode_SetObjKeyCallback (bool(*obj_key_callback)(void *ctx, char *key, int len))
 Set the function to be called back when the key of a key-value pair has been encountered.
void JsonDecode_SetEndObjCallback (bool(*end_obj_callback)(void *ctx))
 Set the function to be called back when an object is ended.
void JsonDecode_SetStartArrayCallback (bool(*start_array_callback)(void *ctx))
 Set the function to be called back when an array is started.
void JsonDecode_SetEndArrayCallback (bool(*end_array_callback)(void *ctx))
 Set the function to be called back when an array is ended.
void JsonDecode_Init (JsonDecode_State *state, void *context)
 Initialize or reset a JsonDecode_State variable.
bool JsonDecode (JsonDecode_State *state, char *text, int len)
 Parse a JSON string.

Detailed Description

The Make Controller JSON library provides a very small and very fast library for parsing and generating json.

From http://www.json.org: "JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read and write. It is easy for machines to parse and generate."

JSON is quite widely used when communicating with web servers, or other network enabled devices. It's nice and small, and easy to work with. It's quite well supported in many programming environments, so it's not a bad option for a communication format when you need to talk to other devices from the Make Controller.

Disclaimer - in an attempt to keep it as small and as simple as possible, this library is not completely full featured at the moment. It doesn't process escaped strings for you, and doesn't deal with some of the more exotic numeric representations outlined in the JSON specification. It does, however, work quite well for most other JSON tasks.

Generating

Generating JSON is pretty simple - just make successive calls to the API to add the desired elements to your string.

You need to provide a few things:

  #define MAX_JSON_LEN 256
  char jsonbuf[MAX_JSON_LEN];
  int remaining = MAX_JSON_LEN;
  JsonEncode_State s;

  char *p = jsonbuf; // keep a pointer to the current location
  JsonEncode_Init(&s); // initialize our state variable
  p = JsonEncode_ObjectOpen(&s, p, &remaining);
  p = JsonEncode_String(&s, p, "hello", &remaining);
  p = JsonEncode_Int(&s, p, 234, &remaining);
  p = JsonEncode_ObjectClose(&s, p, &remaining);
  // now the string in jsonbuf looks like {"hello":234} - beautifully formatted JSON
  int json_len = MAX_JSON_LEN - remaining; // this is the total length of the string in jsonbuf

Note - the library will add the appropriate separators (: or , usually) to the string, depending on the context of the objects and arrays you've opened, or other data you've inserted.

Parsing

Parsing is done using an event-based mechanism. This means you can register for any parse events you care to hear about, and then be called back with their value as they're encountered in the JSON string. Each parse process needs its own JsonDecode_State variable to keep track of where it is.

In each callback, return true to continue parsing, or return false and parsing will stop.

If you need to pass around some context that you would like available in each of the callbacks, you can pass it to JsonDecode_Init() and it will be passed to each of the callbacks you've registered. Otherwise, just pass 0 if you don't need it.

  // first, define the functions that we want to be called back on
  bool on_obj_opened(void* ctx)
  {
    // will be called when an object has been opened...
    return true; // keep parsing
  }
  
  bool on_int(void *ctx, int val)
  {
    iny my_json_int = val;
    // called when an int is encountered...
    return true; // keep parsing
  }
  
  bool on_string(void *ctx, char *string, int len)
  {
    // called when a string is encountered...
    return true; // keep parsing
  }

  // Now, register these callbacks with the JSON parser.
  JsonDecode_SetStartObjCallback(on_obj_opened);
  JsonDecode_SetIntCallback(on_int);
  JsonDecode_SetStringCallback(on_string);

  // Finally, run the parser.
  JsonDecode_State s;
  JsonDecode_Init(&s, 0); // pass 0 if you don't need to use any special context
  char jsonstr[] = "[{\"label\":\"value\",\"label2\":{\"nested\":234}}]";
  JsonDecode(&s, jsonstr, strlen(jsonstr));
  // now each of our callbacks will be triggered at the appropriate time

Thanks to YAJL (http://code.google.com/p/yajl-c) for some design inspiration.


Function Documentation

bool JsonDecode ( JsonDecode_State state,
char *  text,
int  len 
)

Parse a JSON string.

The JSON parser is event based, meaning that you will receive any callbacks you registered for as the elements are encountered in the JSON string.

Parameters:
state A pointer to the JsonDecode_State variable being used for this decode process.
text The JSON string to parse.
len The length of the JSON string.
Returns:
True on a successful parse, false on failure.
Example
  // quotes are escaped since I'm writing it out manually
  JsonDecode_State s;
  char jsonstr[] = "[{\"label\":\"value\",\"label2\":{\"nested\":234}}]";
  JsonDecode_Init(&s, 0);
  JsonDecode(jsonstr, strlen(jsonstr), 0); // don't pass in any context
  // now we expect to be called back on any callbacks we registered.

Definition at line 753 of file json.c.

void JsonDecode_Init ( JsonDecode_State state,
void *  context 
)

Initialize or reset a JsonDecode_State variable.

Do this prior to making a call to JsonDecode().

Parameters:
state A pointer to the JsonDecode_State variable being used for this decode process.
context An optional paramter that your code can use to pass around a known object within the callbacks. Otherwise, just set it to 0

Definition at line 724 of file json.c.

void JsonDecode_SetBoolCallback ( bool(*)(void *ctx, bool val)  bool_callback  ) 

Set the function to be called back when a boolean is parsed.

The function must have the format:

  bool on_bool(void* context, bool value);
which would then be registered like so: The context parameter will be set to whatever you originally passed to JsonDecode_Init(). Since each JsonDecode_State can have a different context, this makes it convenient to know in your callback which one you're currently parsing.

Parameters:
bool_callback The function to be called back.

Definition at line 573 of file json.c.

void JsonDecode_SetEndArrayCallback ( bool(*)(void *ctx)  end_array_callback  ) 

Set the function to be called back when an array is ended.

The right brace - ] - is the closing element of an array. The function must have the format:

  bool on_array_ended(void* context);
which would then be registered like so: The context parameter will be set to whatever you originally passed to JsonDecode_Init(). Since each JsonDecode_State can have a different context, this makes it convenient to know in your callback which one you're currently parsing.

Parameters:
end_array_callback The function to be called back.

Definition at line 712 of file json.c.

void JsonDecode_SetEndObjCallback ( bool(*)(void *ctx)  end_obj_callback  ) 

Set the function to be called back when an object is ended.

The right bracket - } - is the closing element of an object. The function must have the format:

  bool on_obj_ended(void* context);
which would then be registered like so: The context parameter will be set to whatever you originally passed to JsonDecode_Init(). Since each JsonDecode_State can have a different context, this makes it convenient to know in your callback which one you're currently parsing.

Parameters:
end_obj_callback The function to be called back.

Definition at line 668 of file json.c.

void JsonDecode_SetFloatCallback ( bool(*)(void *ctx, float val)  float_callback  ) 

Set the function to be called back when a float is parsed.

The function must have the format:

  bool on_float(void* context, float value);
which would then be registered like so: The context parameter will be set to whatever you originally passed to JsonDecode_Init(). Since each JsonDecode_State can have a different context, this makes it convenient to know in your callback which one you're currently parsing.

Parameters:
float_callback The function to be called back.

Definition at line 552 of file json.c.

void JsonDecode_SetIntCallback ( bool(*)(void *ctx, int val)  int_callback  ) 

Set the function to be called back when an integer is parsed.

The function must have the format:

  bool on_int(void* context, int value);
which would then be registered like so: The context parameter will be set to whatever you originally passed to JsonDecode_Init(). Since each JsonDecode_State can have a different context, this makes it convenient to know in your callback which one you're currently parsing.

Parameters:
int_callback The function to be called back.

Definition at line 531 of file json.c.

void JsonDecode_SetObjKeyCallback ( bool(*)(void *ctx, char *key, int len)  obj_key_callback  ) 

Set the function to be called back when the key of a key-value pair has been encountered.

A key must always be a string in JSON, so you'll get the string back. This is particularly helpful for setting how the next element (the value in the key-value pair) should be handled.

The function must have the format:

  bool on_obj_key(void* context);
which would then be registered like so: The context parameter will be set to whatever you originally passed to JsonDecode_Init(). Since each JsonDecode_State can have a different context, this makes it convenient to know in your callback which one you're currently parsing.

Parameters:
obj_key_callback The function to be called back.

Definition at line 646 of file json.c.

void JsonDecode_SetStartArrayCallback ( bool(*)(void *ctx)  start_array_callback  ) 

Set the function to be called back when an array is started.

The left brace - [ - is the starting element of an array. The function must have the format:

  bool on_array_started(void* context);
which would then be registered like so: The context parameter will be set to whatever you originally passed to JsonDecode_Init(). Since each JsonDecode_State can have a different context, this makes it convenient to know in your callback which one you're currently parsing.

Parameters:
start_array_callback The function to be called back.

Definition at line 690 of file json.c.

void JsonDecode_SetStartObjCallback ( bool(*)(void *ctx)  start_obj_callback  ) 

Set the function to be called back when an object is started.

The left bracket - { - is the opening element of an object. The function must have the format:

  bool on_obj_started(void* context);
which would then be registered like so: The context parameter will be set to whatever you originally passed to JsonDecode_Init(). Since each JsonDecode_State can have a different context, this makes it convenient to know in your callback which one you're currently parsing.

Parameters:
start_obj_callback The function to be called back.

Definition at line 622 of file json.c.

void JsonDecode_SetStringCallback ( bool(*)(void *ctx, char *string, int len)  string_callback  ) 

Set the function to be called back when a string is parsed.

Note - escaped elements in strings are respected, but not processed/removed from the string at the moment, since the internal implementation simply points to the string in the original data. If you have escaped data, you'll need to handle it in your code.

The function must have the format:

  bool on_string(void* context, char* string);
which would then be registered like so: The context parameter will be set to whatever you originally passed to JsonDecode_Init(). Since each JsonDecode_State can have a different context, this makes it convenient to know in your callback which one you're currently parsing.

Parameters:
string_callback The function to be called back.

Definition at line 600 of file json.c.

char* JsonEncode_ArrayClose ( JsonEncode_State state,
char *  buf,
int *  remaining 
)

Close an array.

Adds a closing ']' to the string.

Parameters:
state A pointer to the JsonEncode_State variable being used for this encode process.
buf A pointer to the buffer which contains your JSON string.
remaining A pointer to the count of how many bytes are left in your JSON buffer.
Returns:
A pointer to the JSON buffer after this element has been added, or NULL if there was no room.

Definition at line 273 of file json.c.

char* JsonEncode_ArrayOpen ( JsonEncode_State state,
char *  buf,
int *  remaining 
)

Open up a new JSON array.

This adds an opening '[' to the json string.

Parameters:
state A pointer to the JsonEncode_State variable being used for this encode process.
buf A pointer to the buffer holding the JSON string.
remaining A pointer to the count of how many bytes are left in your JSON buffer.
Returns:
A pointer to the location in the JSON buffer after this element has been added, or NULL if there was no room.

Definition at line 224 of file json.c.

char* JsonEncode_Bool ( JsonEncode_State state,
char *  buf,
bool  value,
int *  remaining 
)

Add a boolean value to a JSON string.

Parameters:
state A pointer to the JsonEncode_State variable being used for this encode process.
buf A pointer to the buffer containing the JSON string.
value The boolean value to be added.
remaining A pointer to the count of bytes remaining in the JSON buffer.
Returns:
A pointer to the JSON buffer after this element has been added, or NULL if there was no room.

Definition at line 408 of file json.c.

void JsonEncode_Init ( JsonEncode_State state  ) 

Initialize or reset the state of a JsonEncode_State variable.

Be sure to do this each time before you start parsing.

Definition at line 129 of file json.c.

char* JsonEncode_Int ( JsonEncode_State state,
char *  buf,
int  value,
int *  remaining 
)

Add an int to a JSON string.

Parameters:
state A pointer to the JsonEncode_State variable being used for this encode process.
buf A pointer to the buffer containing the JSON string.
value The integer to be added.
remaining A pointer to the count of bytes remaining in the JSON buffer.
Returns:
A pointer to the JSON buffer after this element has been added, or NULL if there was no room.

Definition at line 351 of file json.c.

char* JsonEncode_ObjectClose ( JsonEncode_State state,
char *  buf,
int *  remaining 
)

Close a JSON object.

Adds a closing '}' to the string.

Parameters:
state A pointer to the JsonEncode_State variable being used for this encode process.
buf A pointer to the buffer which contains your JSON string.
remaining A pointer to an integer keeping track of how many bytes are left in your JSON buffer.
Returns:
A pointer to the location in the JSON buffer after this element has been added, or NULL if there was no room.

Definition at line 205 of file json.c.

char* JsonEncode_ObjectKey ( JsonEncode_State state,
char *  buf,
const char *  key,
int *  remaining 
)

Set the key for a JSON object.

This is a convenience function that simply calls JsonEncode_String(). It is provided to help enforce the idea that the first member of a JSON object pair must be a string.

See also:
JsonEncode_String()

Definition at line 192 of file json.c.

char* JsonEncode_ObjectOpen ( JsonEncode_State state,
char *  buf,
int *  remaining 
)

Open up a new JSON object.

This adds an opening '{' to the json string.

Parameters:
state A pointer to the JsonEncode_State variable being used for this encode process.
buf A pointer to the buffer holding the JSON string.
remaining A pointer to the count of how many bytes are left in your JSON buffer.
Returns:
A pointer to the location in the JSON buffer after this element has been added, or NULL if there was no room.

Definition at line 143 of file json.c.

char* JsonEncode_String ( JsonEncode_State state,
char *  buf,
const char *  string,
int *  remaining 
)

Add a string to the current JSON string.

Depending on whether you've opened objects, arrays, or other inserted other data, the approprate separating symbols will be added to the string.

Parameters:
state A pointer to the JsonEncode_State variable being used for this encode process.
buf A pointer to the buffer containing the JSON string.
string The string to be added.
remaining A pointer to the count of bytes remaining in the JSON buffer.
Returns:
A pointer to the JSON buffer after this element has been added, or NULL if there was no room.

Definition at line 295 of file json.c.