• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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