21 CxJsonStatus cxJsonNext(CxJson *json, CxJsonValue **value); |
21 CxJsonStatus cxJsonNext(CxJson *json, CxJsonValue **value); |
22 |
22 |
23 void cxJsonDestroy(CxJson *json); |
23 void cxJsonDestroy(CxJson *json); |
24 ``` |
24 ``` |
25 |
25 |
26 <warning> |
26 The first step is to initialize a `CxJson` structure with a call to `cxJsonInit()`, |
27 TODO: document |
27 specifying the allocator that shall be used for allocating values of type `CxJsonValue`. |
28 </warning> |
28 |
|
29 Specifying `NULL` as `allocator` is allowed, in which case the `cxDefaultAllocator` will be used. |
|
30 |
|
31 The actual parsing is an interleaving invocation of the `cxJsonFill()` (or `cxJsonFilln()`) and `cxJsonNext()` functions. |
|
32 The `cxJsonFill()` function is a convenience function, that accepts UCX strings and normal zero-terminated C strings. |
|
33 |
|
34 Calling `cxJsonNext()` will return with `CX_JSON_NO_ERROR` (= zero) for each JSON value that is successfully parsed, |
|
35 and stores the pointer to the allocated value in the variable pointed to by `value`. |
|
36 |
|
37 > The parser is capable of parsing multiple consecutive JSON values. |
|
38 > If those values are not objects or arrays, they must, however, be separated by any whitespace character. |
|
39 |
|
40 When all the data from the input buffer was successfully consumed, `cxJsonNext()` returns `CX_JSON_NO_DATA`. |
|
41 |
|
42 If `cxJsonNext()` returns `CX_JSON_INCOMPLETE_DATA` it means that the input buffer is exhausted, |
|
43 but the parsed input does not constitute a complete JSON value. |
|
44 In that case, you can call `cxJsonFill()` again to add more data and continue with `cxJsonNext()`. |
|
45 |
|
46 A complete list of all status codes can be seen [below](#list-of-status-codes). |
|
47 |
|
48 If you want to reuse a `CxJson` structure, you can call `cxJsonReset()`, even if the last operation was a failure. |
|
49 Otherwise, you need to call `cxJsonDestroy()` when you are done with the parser. |
29 |
50 |
30 ### List of Status Codes |
51 ### List of Status Codes |
31 |
52 |
32 Below is a full list of status codes for `cxJsonNext()`. |
53 Below is a full list of status codes for `cxJsonNext()`. |
33 |
54 |
199 |
220 |
200 CxJsonValue* cxJsonObjPutLiteral(CxJsonValue* obj, |
221 CxJsonValue* cxJsonObjPutLiteral(CxJsonValue* obj, |
201 cxstring name, CxJsonLiteral lit); |
222 cxstring name, CxJsonLiteral lit); |
202 ``` |
223 ``` |
203 |
224 |
204 <warning> |
225 The `cxJsonCreateXY()`-family of functions can be used to create JSON values which are allocated by the specified `allocator`. |
205 TODO: document |
226 If you specify `NULL` as allocator, the `cxDefaultAllocator` is used. |
206 </warning> |
227 |
|
228 If you want to add created values to a JSON array or JSON object, |
|
229 you can use `cxJsonArrAddValues()` or `cxJsonObjPut()`, respectively. |
|
230 However, it is usually more convenient to use one of the other functions, as they automatically create the JSON value for. |
|
231 |
|
232 ```C |
|
233 #include <cx/json.h> |
|
234 |
|
235 CxJsonValue* arr = cxJsonCreateArr(NULL); |
|
236 |
|
237 // this is equivalent... |
|
238 CxJsonValue* x = cxJsonCreateInteger(NULL, 47); |
|
239 CxJsonValue* y = cxJsonCreateInteger(NULL, 11); |
|
240 cxJsonArrAddValues(arr, (CxJsonValue*[]){x, y}, 2); |
|
241 |
|
242 // ... to this |
|
243 cxJsonArrAddIntegers(arr, (int64_t[]){47, 11}, 2); |
|
244 ``` |
|
245 |
|
246 The following example shows how to construct a complete JSON object. |
|
247 |
|
248 ```C |
|
249 CxJsonValue *obj = cxJsonCreateObj(NULL); |
|
250 |
|
251 cxJsonObjPutLiteral(obj, CX_STR("bool"), CX_JSON_FALSE); |
|
252 cxJsonObjPutInteger(obj, CX_STR("int"), 47); |
|
253 |
|
254 CxJsonValue *strings = cxJsonObjPutArr(obj, CX_STR("strings")); |
|
255 cxJsonArrAddStrings(strings, (const char*[]) {"hello", "world"}, 2); |
|
256 |
|
257 CxJsonValue *nested = cxJsonObjPutObj(obj, CX_STR("nested")); |
|
258 CxJsonValue *objects = cxJsonObjPutArr(nested, CX_STR("objects")); |
|
259 CxJsonValue *obj_in_arr[2] = { |
|
260 cxJsonCreateObj(NULL), |
|
261 cxJsonCreateObj(NULL), |
|
262 }; |
|
263 cxJsonObjPutInteger(obj_in_arr[0], CX_STR("name1"), 1); |
|
264 cxJsonObjPutInteger(obj_in_arr[0], CX_STR("name2"), 3); |
|
265 |
|
266 cxJsonObjPutInteger(obj_in_arr[1], CX_STR("name2"), 7); |
|
267 cxJsonObjPutInteger(obj_in_arr[1], CX_STR("name1"), 3); |
|
268 |
|
269 cxJsonArrAddValues(objects, obj_in_arr, 2); |
|
270 |
|
271 cxJsonArrAddNumbers(cxJsonObjPutArr(nested, CX_STR("floats")), |
|
272 (double[]){3.1415, 47.11, 8.15}, 3); |
|
273 |
|
274 cxJsonArrAddLiterals(cxJsonObjPutArr(nested, CX_STR("literals")), |
|
275 (CxJsonLiteral[]){CX_JSON_TRUE, CX_JSON_NULL, CX_JSON_FALSE}, 3); |
|
276 |
|
277 CxJsonValue *ints = cxJsonObjPutArr(nested, CX_STR("ints")); |
|
278 cxJsonArrAddIntegers(ints, (int64_t[]){4, 8, 15}, 3); |
|
279 |
|
280 CxJsonValue *nested_array = cxJsonCreateArr(NULL); |
|
281 cxJsonArrAddValues(ints, &nested_array, 1); |
|
282 cxJsonArrAddIntegers(nested_array, (int64_t[]){16, 23}, 2); |
|
283 cxJsonArrAddIntegers(ints, (int64_t[]){42}, 1); |
|
284 |
|
285 CxJsonWriter w = cxJsonWriterPretty(true); |
|
286 cxJsonWrite(stdout, obj, (cx_write_func) fwrite, &w); |
|
287 |
|
288 cxJsonValueFree(obj); |
|
289 ``` |
|
290 |
|
291 The above code writes the following output to `stdout`: |
|
292 |
|
293 ```JSON |
|
294 { |
|
295 "bool": false, |
|
296 "int": 47, |
|
297 "nested": { |
|
298 "floats": [3.1415, 47.11, 8.15], |
|
299 "ints": [4, 8, 15, [16, 23], 42], |
|
300 "literals": [true, null, false], |
|
301 "objects": [{ |
|
302 "name1": 1, |
|
303 "name2": 3 |
|
304 }, { |
|
305 "name1": 3, |
|
306 "name2": 7 |
|
307 }] |
|
308 }, |
|
309 "strings": ["hello", "world"] |
|
310 } |
|
311 ``` |
207 |
312 |
208 ## Writer |
313 ## Writer |
209 |
314 |
210 ```C |
315 ```C |
211 #include <cx/json.h> |
316 #include <cx/json.h> |