Access to data
Once application successfully parses input JSON string, LwJSON creates set of tokens in hierarchical order with tree for children tokens.
To simplify data extraction and to quickly find/access-to given object and token, LwJSON implements simple find algorithm based on path formatting.
Traverse object
Valid JSON input starts with object ({) or array ([). Anything else is invalid JSON object.
When lwjson_parse() successfully processes input data, application may access JSON tokens
with simple loop. Every token is part of linked list and has tree organization for children objects.
Note
Children objects are only available for object and array types
To traverse through all elements, application must first get top object. It can then loop through all in linked list until it reaches zero.
If the token type is object or array, application must check children nodes for more token data.
1#include <stdio.h>
2#include "lwjson/lwjson.h"
3
4/* LwJSON instance and tokens */
5static lwjson_token_t tokens[128];
6static lwjson_t lwjson;
7
8/* Parse JSON */
9void
10example_traverse_run(void) {
11 /* Initialize and pass statically allocated tokens */
12 lwjson_init(&lwjson, tokens, LWJSON_ARRAYSIZE(tokens));
13
14 /* Try to parse input string */
15 if (lwjson_parse(&lwjson, "{\"mykey\":\"myvalue\",\"num\":1,\"obj\":{},\"arr\":[1,2,3,4]}") == lwjsonOK) {
16 lwjson_token_t* t;
17 printf("JSON parsed..\r\n");
18
19 /* Get very first token as top object */
20 t = lwjson_get_first_token(&lwjson);
21 if (t->type == LWJSON_TYPE_ARRAY) {
22 printf("JSON starts with array..\r\n");
23 } else if (t->type == LWJSON_TYPE_OBJECT) {
24 printf("JSON starts with object..\r\n");
25 } else {
26 printf("This should never happen..\r\n");
27 }
28
29 /* Now print all keys in the object */
30 for (const lwjson_token_t* tkn = lwjson_get_first_child(t); tkn != NULL; tkn = tkn->next) {
31 printf("Token: %.*s", (int)tkn->token_name_len, tkn->token_name);
32 if (tkn->type == LWJSON_TYPE_ARRAY || tkn->type == LWJSON_TYPE_OBJECT) {
33 printf(": Token is array or object...check children tokens if any, in recursive mode..");
34 /* Get first child of token */
35 //lwjson_get_first_child(tkn);
36 }
37 printf("\n");
38 }
39
40 /* Call this when not used anymore */
41 lwjson_free(&lwjson);
42 }
43}
Tip
Check lwjson_print_json() to print data on stream output
Find token in JSON tree
Instead of manually traversing through all tokens, LwJSON implements simple search algorithm to quickly get token from application standpoint.
Let’s consider following JSON as input:
{
"name":"John",
"born": {
"city": "Munich",
"year": 1993
},
"cars":[
{
"brand":"Porsche",
"year":2018
},
{
"brand":"Range",
"year":2020,
"repainted":true
}
]
}
There is one John, born in Munich in 1993 and has 2 cars, Porsche and Range.
nameis string with valueJohnbornis object with2fieldscarsis array of2objectsobject 1
brandis set to Porscheyearis set to2018
object 2
brandis set to Rangeyearis set to2020repaintedis set totrueas this car was recently repainted
To find the person’s name, application must first name key and print its value.
This can be done by scanning entire object and check which token matches name keyword.
LwJSON implements find functionality to find the token in simple way.
This is done by providing full path to token in JSON tree, separated by dot . character.
To find person name, application would then simply call lwjson_find() and pass name as path parameter.
If token exists, function will return handle of the token where application can print its value.
If application is interested in city of birth, it will set path as born.city and search
algorithm will:
First search for
borntoken and check if it is objectIt will enter the object and search for
citytoken and return it on matchIt will return
NULLof object is not found
Tip
Application shall use lwjson_find() to get the token based on input path.
When JSON contains arrays (these do not have keys), special character # may be used,
indicating any element in array to be checked until first match is found.
cars.#.brandwill return first token matching path, the one with string valuePorschein first objectcars.#.repaintedwill return first token matching path, the one with boolean valuetruein second object
In first case, brand keyword exists already in first object, so find function will get the match immediately.
Because in second case, repainted only exists in second object, function will return value from second object.
Access array index
It is possible to access specific array index by adding decimal number after hash character, in format #[0-9]+
cars.#0.brandwill returnbrandtoken from first object in array (index = 0) with value set to Porschecars.#1.brandwill returnbrandtoken from second object in array (index = 1) with value set to Range
To retrieve full object of the array, application may only apply #[0.9]+ in search pattern.
cars.#0will return first object token in arraycars.#1will return second object token in arraycars.#will return error as there is no valid index. Usecarsto retrieve full array
Warning
Passing path in format path.to.cars.# (hashtag as last element without index number) will always return NULL
as this is considered invalid path. To retrieve full array, pass path to array path.to.cars only, without trailling #.