Vergil Cola
/
MQTTGatewayK64
Fork of my MQTTGateway
jsmn/README.md@0:f1d3878b8dd9, 2017-04-08 (annotated)
- Committer:
- vpcola
- Date:
- Sat Apr 08 14:45:51 2017 +0000
- Revision:
- 0:f1d3878b8dd9
Initial commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
vpcola | 0:f1d3878b8dd9 | 1 | |
vpcola | 0:f1d3878b8dd9 | 2 | JSMN |
vpcola | 0:f1d3878b8dd9 | 3 | ==== |
vpcola | 0:f1d3878b8dd9 | 4 | |
vpcola | 0:f1d3878b8dd9 | 5 | jsmn (pronounced like 'jasmine') is a minimalistic JSON parser in C. It can be |
vpcola | 0:f1d3878b8dd9 | 6 | easily integrated into resource-limited or embedded projects. |
vpcola | 0:f1d3878b8dd9 | 7 | |
vpcola | 0:f1d3878b8dd9 | 8 | You can find more information about JSON format at [json.org][1] |
vpcola | 0:f1d3878b8dd9 | 9 | |
vpcola | 0:f1d3878b8dd9 | 10 | Library sources are available at https://github.com/zserge/jsmn |
vpcola | 0:f1d3878b8dd9 | 11 | |
vpcola | 0:f1d3878b8dd9 | 12 | The web page with some information about jsmn can be found at |
vpcola | 0:f1d3878b8dd9 | 13 | [http://zserge.com/jsmn.html][2] |
vpcola | 0:f1d3878b8dd9 | 14 | |
vpcola | 0:f1d3878b8dd9 | 15 | Philosophy |
vpcola | 0:f1d3878b8dd9 | 16 | ---------- |
vpcola | 0:f1d3878b8dd9 | 17 | |
vpcola | 0:f1d3878b8dd9 | 18 | Most JSON parsers offer you a bunch of functions to load JSON data, parse it |
vpcola | 0:f1d3878b8dd9 | 19 | and extract any value by its name. jsmn proves that checking the correctness of |
vpcola | 0:f1d3878b8dd9 | 20 | every JSON packet or allocating temporary objects to store parsed JSON fields |
vpcola | 0:f1d3878b8dd9 | 21 | often is an overkill. |
vpcola | 0:f1d3878b8dd9 | 22 | |
vpcola | 0:f1d3878b8dd9 | 23 | JSON format itself is extremely simple, so why should we complicate it? |
vpcola | 0:f1d3878b8dd9 | 24 | |
vpcola | 0:f1d3878b8dd9 | 25 | jsmn is designed to be **robust** (it should work fine even with erroneous |
vpcola | 0:f1d3878b8dd9 | 26 | data), **fast** (it should parse data on the fly), **portable** (no superfluous |
vpcola | 0:f1d3878b8dd9 | 27 | dependencies or non-standard C extensions). And of course, **simplicity** is a |
vpcola | 0:f1d3878b8dd9 | 28 | key feature - simple code style, simple algorithm, simple integration into |
vpcola | 0:f1d3878b8dd9 | 29 | other projects. |
vpcola | 0:f1d3878b8dd9 | 30 | |
vpcola | 0:f1d3878b8dd9 | 31 | Features |
vpcola | 0:f1d3878b8dd9 | 32 | -------- |
vpcola | 0:f1d3878b8dd9 | 33 | |
vpcola | 0:f1d3878b8dd9 | 34 | * compatible with C89 |
vpcola | 0:f1d3878b8dd9 | 35 | * no dependencies (even libc!) |
vpcola | 0:f1d3878b8dd9 | 36 | * highly portable (tested on x86/amd64, ARM, AVR) |
vpcola | 0:f1d3878b8dd9 | 37 | * about 200 lines of code |
vpcola | 0:f1d3878b8dd9 | 38 | * extremely small code footprint |
vpcola | 0:f1d3878b8dd9 | 39 | * API contains only 2 functions |
vpcola | 0:f1d3878b8dd9 | 40 | * no dynamic memory allocation |
vpcola | 0:f1d3878b8dd9 | 41 | * incremental single-pass parsing |
vpcola | 0:f1d3878b8dd9 | 42 | * library code is covered with unit-tests |
vpcola | 0:f1d3878b8dd9 | 43 | |
vpcola | 0:f1d3878b8dd9 | 44 | Design |
vpcola | 0:f1d3878b8dd9 | 45 | ------ |
vpcola | 0:f1d3878b8dd9 | 46 | |
vpcola | 0:f1d3878b8dd9 | 47 | The rudimentary jsmn object is a **token**. Let's consider a JSON string: |
vpcola | 0:f1d3878b8dd9 | 48 | |
vpcola | 0:f1d3878b8dd9 | 49 | '{ "name" : "Jack", "age" : 27 }' |
vpcola | 0:f1d3878b8dd9 | 50 | |
vpcola | 0:f1d3878b8dd9 | 51 | It holds the following tokens: |
vpcola | 0:f1d3878b8dd9 | 52 | |
vpcola | 0:f1d3878b8dd9 | 53 | * Object: `{ "name" : "Jack", "age" : 27}` (the whole object) |
vpcola | 0:f1d3878b8dd9 | 54 | * Strings: `"name"`, `"Jack"`, `"age"` (keys and some values) |
vpcola | 0:f1d3878b8dd9 | 55 | * Number: `27` |
vpcola | 0:f1d3878b8dd9 | 56 | |
vpcola | 0:f1d3878b8dd9 | 57 | In jsmn, tokens do not hold any data, but point to token boundaries in JSON |
vpcola | 0:f1d3878b8dd9 | 58 | string instead. In the example above jsmn will create tokens like: Object |
vpcola | 0:f1d3878b8dd9 | 59 | [0..31], String [3..7], String [12..16], String [20..23], Number [27..29]. |
vpcola | 0:f1d3878b8dd9 | 60 | |
vpcola | 0:f1d3878b8dd9 | 61 | Every jsmn token has a type, which indicates the type of corresponding JSON |
vpcola | 0:f1d3878b8dd9 | 62 | token. jsmn supports the following token types: |
vpcola | 0:f1d3878b8dd9 | 63 | |
vpcola | 0:f1d3878b8dd9 | 64 | * Object - a container of key-value pairs, e.g.: |
vpcola | 0:f1d3878b8dd9 | 65 | `{ "foo":"bar", "x":0.3 }` |
vpcola | 0:f1d3878b8dd9 | 66 | * Array - a sequence of values, e.g.: |
vpcola | 0:f1d3878b8dd9 | 67 | `[ 1, 2, 3 ]` |
vpcola | 0:f1d3878b8dd9 | 68 | * String - a quoted sequence of chars, e.g.: `"foo"` |
vpcola | 0:f1d3878b8dd9 | 69 | * Primitive - a number, a boolean (`true`, `false`) or `null` |
vpcola | 0:f1d3878b8dd9 | 70 | |
vpcola | 0:f1d3878b8dd9 | 71 | Besides start/end positions, jsmn tokens for complex types (like arrays |
vpcola | 0:f1d3878b8dd9 | 72 | or objects) also contain a number of child items, so you can easily follow |
vpcola | 0:f1d3878b8dd9 | 73 | object hierarchy. |
vpcola | 0:f1d3878b8dd9 | 74 | |
vpcola | 0:f1d3878b8dd9 | 75 | This approach provides enough information for parsing any JSON data and makes |
vpcola | 0:f1d3878b8dd9 | 76 | it possible to use zero-copy techniques. |
vpcola | 0:f1d3878b8dd9 | 77 | |
vpcola | 0:f1d3878b8dd9 | 78 | Install |
vpcola | 0:f1d3878b8dd9 | 79 | ------- |
vpcola | 0:f1d3878b8dd9 | 80 | |
vpcola | 0:f1d3878b8dd9 | 81 | To clone the repository you should have Git installed. Just run: |
vpcola | 0:f1d3878b8dd9 | 82 | |
vpcola | 0:f1d3878b8dd9 | 83 | $ git clone https://github.com/zserge/jsmn |
vpcola | 0:f1d3878b8dd9 | 84 | |
vpcola | 0:f1d3878b8dd9 | 85 | Repository layout is simple: jsmn.c and jsmn.h are library files, tests are in |
vpcola | 0:f1d3878b8dd9 | 86 | the jsmn\_test.c, you will also find README, LICENSE and Makefile files inside. |
vpcola | 0:f1d3878b8dd9 | 87 | |
vpcola | 0:f1d3878b8dd9 | 88 | To build the library, run `make`. It is also recommended to run `make test`. |
vpcola | 0:f1d3878b8dd9 | 89 | Let me know, if some tests fail. |
vpcola | 0:f1d3878b8dd9 | 90 | |
vpcola | 0:f1d3878b8dd9 | 91 | If build was successful, you should get a `libjsmn.a` library. |
vpcola | 0:f1d3878b8dd9 | 92 | The header file you should include is called `"jsmn.h"`. |
vpcola | 0:f1d3878b8dd9 | 93 | |
vpcola | 0:f1d3878b8dd9 | 94 | API |
vpcola | 0:f1d3878b8dd9 | 95 | --- |
vpcola | 0:f1d3878b8dd9 | 96 | |
vpcola | 0:f1d3878b8dd9 | 97 | Token types are described by `jsmntype_t`: |
vpcola | 0:f1d3878b8dd9 | 98 | |
vpcola | 0:f1d3878b8dd9 | 99 | typedef enum { |
vpcola | 0:f1d3878b8dd9 | 100 | JSMN_UNDEFINED = 0, |
vpcola | 0:f1d3878b8dd9 | 101 | JSMN_OBJECT = 1, |
vpcola | 0:f1d3878b8dd9 | 102 | JSMN_ARRAY = 2, |
vpcola | 0:f1d3878b8dd9 | 103 | JSMN_STRING = 3, |
vpcola | 0:f1d3878b8dd9 | 104 | JSMN_PRIMITIVE = 4 |
vpcola | 0:f1d3878b8dd9 | 105 | } jsmntype_t; |
vpcola | 0:f1d3878b8dd9 | 106 | |
vpcola | 0:f1d3878b8dd9 | 107 | **Note:** Unlike JSON data types, primitive tokens are not divided into |
vpcola | 0:f1d3878b8dd9 | 108 | numbers, booleans and null, because one can easily tell the type using the |
vpcola | 0:f1d3878b8dd9 | 109 | first character: |
vpcola | 0:f1d3878b8dd9 | 110 | |
vpcola | 0:f1d3878b8dd9 | 111 | * <code>'t', 'f'</code> - boolean |
vpcola | 0:f1d3878b8dd9 | 112 | * <code>'n'</code> - null |
vpcola | 0:f1d3878b8dd9 | 113 | * <code>'-', '0'..'9'</code> - number |
vpcola | 0:f1d3878b8dd9 | 114 | |
vpcola | 0:f1d3878b8dd9 | 115 | Token is an object of `jsmntok_t` type: |
vpcola | 0:f1d3878b8dd9 | 116 | |
vpcola | 0:f1d3878b8dd9 | 117 | typedef struct { |
vpcola | 0:f1d3878b8dd9 | 118 | jsmntype_t type; // Token type |
vpcola | 0:f1d3878b8dd9 | 119 | int start; // Token start position |
vpcola | 0:f1d3878b8dd9 | 120 | int end; // Token end position |
vpcola | 0:f1d3878b8dd9 | 121 | int size; // Number of child (nested) tokens |
vpcola | 0:f1d3878b8dd9 | 122 | } jsmntok_t; |
vpcola | 0:f1d3878b8dd9 | 123 | |
vpcola | 0:f1d3878b8dd9 | 124 | **Note:** string tokens point to the first character after |
vpcola | 0:f1d3878b8dd9 | 125 | the opening quote and the previous symbol before final quote. This was made |
vpcola | 0:f1d3878b8dd9 | 126 | to simplify string extraction from JSON data. |
vpcola | 0:f1d3878b8dd9 | 127 | |
vpcola | 0:f1d3878b8dd9 | 128 | All job is done by `jsmn_parser` object. You can initialize a new parser using: |
vpcola | 0:f1d3878b8dd9 | 129 | |
vpcola | 0:f1d3878b8dd9 | 130 | jsmn_parser parser; |
vpcola | 0:f1d3878b8dd9 | 131 | jsmntok_t tokens[10]; |
vpcola | 0:f1d3878b8dd9 | 132 | |
vpcola | 0:f1d3878b8dd9 | 133 | jsmn_init(&parser); |
vpcola | 0:f1d3878b8dd9 | 134 | |
vpcola | 0:f1d3878b8dd9 | 135 | // js - pointer to JSON string |
vpcola | 0:f1d3878b8dd9 | 136 | // tokens - an array of tokens available |
vpcola | 0:f1d3878b8dd9 | 137 | // 10 - number of tokens available |
vpcola | 0:f1d3878b8dd9 | 138 | jsmn_parse(&parser, js, strlen(js), tokens, 10); |
vpcola | 0:f1d3878b8dd9 | 139 | |
vpcola | 0:f1d3878b8dd9 | 140 | This will create a parser, and then it tries to parse up to 10 JSON tokens from |
vpcola | 0:f1d3878b8dd9 | 141 | the `js` string. |
vpcola | 0:f1d3878b8dd9 | 142 | |
vpcola | 0:f1d3878b8dd9 | 143 | A non-negative return value of `jsmn_parse` is the number of tokens actually |
vpcola | 0:f1d3878b8dd9 | 144 | used by the parser. |
vpcola | 0:f1d3878b8dd9 | 145 | Passing NULL instead of the tokens array would not store parsing results, but |
vpcola | 0:f1d3878b8dd9 | 146 | instead the function will return the value of tokens needed to parse the given |
vpcola | 0:f1d3878b8dd9 | 147 | string. This can be useful if you don't know yet how many tokens to allocate. |
vpcola | 0:f1d3878b8dd9 | 148 | |
vpcola | 0:f1d3878b8dd9 | 149 | If something goes wrong, you will get an error. Error will be one of these: |
vpcola | 0:f1d3878b8dd9 | 150 | |
vpcola | 0:f1d3878b8dd9 | 151 | * `JSMN_ERROR_INVAL` - bad token, JSON string is corrupted |
vpcola | 0:f1d3878b8dd9 | 152 | * `JSMN_ERROR_NOMEM` - not enough tokens, JSON string is too large |
vpcola | 0:f1d3878b8dd9 | 153 | * `JSMN_ERROR_PART` - JSON string is too short, expecting more JSON data |
vpcola | 0:f1d3878b8dd9 | 154 | |
vpcola | 0:f1d3878b8dd9 | 155 | If you get `JSON_ERROR_NOMEM`, you can re-allocate more tokens and call |
vpcola | 0:f1d3878b8dd9 | 156 | `jsmn_parse` once more. If you read json data from the stream, you can |
vpcola | 0:f1d3878b8dd9 | 157 | periodically call `jsmn_parse` and check if return value is `JSON_ERROR_PART`. |
vpcola | 0:f1d3878b8dd9 | 158 | You will get this error until you reach the end of JSON data. |
vpcola | 0:f1d3878b8dd9 | 159 | |
vpcola | 0:f1d3878b8dd9 | 160 | Other info |
vpcola | 0:f1d3878b8dd9 | 161 | ---------- |
vpcola | 0:f1d3878b8dd9 | 162 | |
vpcola | 0:f1d3878b8dd9 | 163 | This software is distributed under [MIT license](http://www.opensource.org/licenses/mit-license.php), |
vpcola | 0:f1d3878b8dd9 | 164 | so feel free to integrate it in your commercial products. |
vpcola | 0:f1d3878b8dd9 | 165 | |
vpcola | 0:f1d3878b8dd9 | 166 | [1]: http://www.json.org/ |
vpcola | 0:f1d3878b8dd9 | 167 | [2]: http://zserge.com/jsmn.html |