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.
name
is string with valueJohn
born
is object with2
fieldscars
is array of2
objectsobject 1
brand
is set to Porscheyear
is set to2018
object 2
brand
is set to Rangeyear
is set to2020
repainted
is set totrue
as 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
born
token and check if it is objectIt will enter the object and search for
city
token and return it on matchIt will return
NULL
of 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.#.brand
will return first token matching path, the one with string valuePorsche
in first objectcars.#.repainted
will return first token matching path, the one with boolean valuetrue
in 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.brand
will returnbrand
token from first object in array (index = 0
) with value set to Porschecars.#1.brand
will returnbrand
token 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.#0
will return first object token in arraycars.#1
will return second object token in arraycars.#
will return error as there is no valid index. Usecars
to 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 #
.