Skip to content
Rob Dobson edited this page Mar 15, 2024 · 8 revisions

Raft JSON

Raft makes extensive use of JSON for configuration and message passing

Raft provides a JSON parsing class called RaftJson and uses JSON extensively for configuration and message passing. Under the hood RaftJson does JSON parsing on-demand and has zero net heap-memory overhead.

RaftJson is almost entirely focused on efficiently extracting values from JSON documents. Limited capabilities are also provided for generating JSON documents - such as conversion of a vector of name+value pairs into a JSON document.

JSON Paths

A key part of Raft JSON handling is the use of JSON paths which use a syntax similar to simplified XPath.

A JSON path is a series of one or more JSON keys separated by forward-slash (/) characters and array elements can be accessed using [].

For example in the following JSON document:

{ "a":{ "b":{ "c":1234, "d":[5,6,7,8] } } }

the value 1234 can be accessed using the JSON path "a/b/c" And the path a/b/d[1] references the 6 in the array called "d"

Raft JSON implementation

The main class which handles JSON is called RaftJson.

Constructing RaftJson objects

This is the form for the constructors of RaftJson objects.

RaftJson(const char* pJsonStr, bool makeCopy = true, RaftJsonIF* pChainedRaftJson = nullptr);

RaftJson objects can be constructed from a string. The first parameter in the constructor is the string (either a C string pointer or an Arduino String reference).

If the string is in non-volatile storage then the makeCopy flag can be used to ensure that no additional heap space is used.

The final parameter is, optionally, a pointer to a RaftJson object to be chained to this one. This allows for a "cascading" approach (similar to the way W3C cascading style sheets CSS are used) to searching for a JSON key. For example, if a key named "test" is to be used at some later point in your app then you can either define it in the object being constructed or the chain of RaftJson objects that have been added in this way will be searched in turn.

Accessing simple JSON values using RaftJson

There are several methods for accessing simple values (Strings, floats, numbers, booleans) from the JSON document.

String getString(const char* pDataPath, const char* defaultValue);

double getDouble(const char* pDataPath, double defaultValue);

long getLong(const char* pDataPath, long defaultValue);

bool getBool(const char* pDataPath, bool defaultValue);

The pDataPath parameter is used to search the JSON document for the value to be returned. As described above this can make use of an XPath-like syntax (e.g. "a/b/c[0]/d")

To convert the numeric values to C/C++ types, simply cast them, for instance if a JSON document contains:

{
    "myValue": 123
}

then:

int myValue = config.getLong("myValue", -1);

will extract the value referred by the key "myValue" (i.e. 123). If the key "myValue" did not exist then -1 would be returned.

Accessing array values

To extract an array:

bool getArrayElems(const char *pDataPath, std::vector<String>& strList);

Returns false if no matching key can be found in the JSON document.

Otherwise a C++ standard library vector of String objects is returned containing the (text) elements of the array. If further processing is required on the returned vector then each element can be used to construct further RaftJson objects and values extracted accordingly.

Other helpful functions

bool getKeys(const char *pDataPath, std::vector<String>& keysVector);

Returns a vector of key strings for the object located in the JSON document.

bool contains(const char* pDataPath);

Returns true if the key matching data path is found.

RaftJsonType getType(const char* pDataPath, int &arrayLen);

Returns the type of JSON element found using the data path. RaftJsonType is an enumeration:

typedef enum
{
    RAFT_JSON_UNDEFINED = 0,
    RAFT_JSON_OBJECT = 1,
    RAFT_JSON_ARRAY = 2,
    RAFT_JSON_STRING = 3,
    RAFT_JSON_BOOLEAN = 4,
    RAFT_JSON_NUMBER = 5,
    RAFT_JSON_NULL = 6
} RaftJsonType;

Clone this wiki locally