1# LEJP JSON Stream Parser 2 3||| 4|---|---|---| 5|cmake| `LWS_WITH_LEJP`| 6|Header| ./include/libwebsockets/lws-lejp.h| 7|api-test| ./minimal-examples/api-tests/api-test-lejp/| 8|test app| ./test-apps/test-lejp.c -> libwebsockets-test-lejp| 9 10LEJP is a lightweight JSON stream parser. 11 12The features are: 13 14 - completely immune to input fragmentation, give it any size blocks of JSON as 15 they become available, 1 byte, or 100K at a time give identical parsing 16 results 17 - input chunks discarded as they are parsed, whole JSON never needed in memory 18 - nonrecursive, fixed stack usage of a few dozen bytes 19 - no heap allocations at all, just requires ~500 byte context usually on 20 caller stack 21 - creates callbacks to a user-provided handler as members are parsed out 22 - no payload size limit, supports huge / endless strings bigger than 23 system memory 24 - collates utf-8 text payloads into a 250-byte chunk buffer in the json parser 25 context object for ease of access 26 27## Type handling 28 29LEJP leaves all numbers in text form, they are signalled in different callbacks 30according to int or float, but delivered as text strings in the first 31`ctx->npos` chars of `ctx->buf`. 32 33For numeric types, you would typically use `atoi()` or similar to recover the 34number as a host type. 35 36## Callback reasons 37 38The user callback does not have to handle any callbacks, it only needs to 39process the data for the ones it is interested in. 40 41|Callback reason|JSON structure|Associated data| 42|---|---|---| 43|`LEJPCB_CONSTRUCTED`|Created the parse context|| 44|`LEJPCB_DESTRUCTED`|Destroyed the parse context|| 45|`LEJPCB_COMPLETE`|The parsing completed OK|| 46|`LEJPCB_FAILED`|The parsing failed|| 47|`LEJPCB_VAL_TRUE`|boolean true|| 48|`LEJPCB_VAL_FALSE`|boolean false|| 49|`LEJPCB_VAL_NULL`|explicit NULL|| 50|`LEJPCB_PAIR_NAME`|The name part of a JSON `key: value` map pair|`ctx->buf`| 51|`LEJPCB_VAL_STR_START`|A UTF-8 string is starting|| 52|`LEJPCB_VAL_STR_CHUNK`|The next string chunk|`ctx->npos` bytes in `ctx->buf`| 53|`LEJPCB_VAL_STR_END`|The last string chunk|`ctx->npos` bytes in `ctx->buf`| 54|`LEJPCB_ARRAY_START`|An array is starting|| 55|`LEJPCB_ARRAY_END`|An array has ended|| 56|`LEJPCB_OBJECT_START`|A JSON object is starting|| 57|`LEJPCB_OBJECT_END`|A JSON object has ended|| 58 59## Handling JSON UTF-8 strings 60 61When a string is parsed, an advisory callback of `LECPCB_VAL_STR_START` occurs 62first. No payload is delivered with the START callback. 63 64Payload is collated into `ctx->buf[]`, the valid length is in `ctx->npos`. 65 66For short strings or blobs where the length is known, the whole payload is 67delivered in a single `LECPCB_VAL_STR_END` callback. 68 69For payloads larger than the size of `ctx->buf[]`, `LECPCB_VAL_STR_CHUNK` 70callbacks occur delivering each sequential bufferload. 71 72The last chunk (which may be zero length) is delievered by `LECPCB_VAL_STR_END`. 73 74## Parsing paths 75 76LEJP maintains a "parsing path" in `ctx->path` that represents the context of 77the callback events. As a convenience, at LEJP context creation time, you can 78pass in an array of path strings you want to match on, and have any match 79checkable in the callback using `ctx->path_match`, it's 0 if no active match, 80or the match index from your path array starting from 1 for the first entry. 81 82|CBOR element|Representation in path| 83|---|---| 84|JSON Array|`[]`| 85|JSON Map|`.`| 86|JSON Map entry key string|`keystring`| 87 88 89 90## Comparison with LECP (CBOR parser) 91 92LECP is based on the same principles as LEJP and shares most of the callbacks. 93The major differences: 94 95 - LEJP value callbacks all appear in `ctx->buf[]`, ie, floating-point is 96 provided to the callback in ascii form like `"1.0"`. CBOR provides a more 97 strict typing system, and the different type values are provided either in 98 `ctx->buf[]` for blobs or utf-8 text strtings, or the `item.u` union for 99 converted types, with additional callback reasons specific to each type. 100 101 - CBOR "maps" use `_OBJECT_START` and `_END` parsing callbacks around the 102 key / value pairs. LEJP has a special callback type `PAIR_NAME` for the 103 key string / integer, but in LECP these are provided as generic callbacks 104 dependent on type, ie, generic string callbacks or integer ones, and the 105 value part is represented according to whatever comes. 106 107 108