12b15cb3dSCy Schubert 22b15cb3dSCy SchubertJSMN 32b15cb3dSCy Schubert==== 42b15cb3dSCy Schubert 52b15cb3dSCy Schubertjsmn (pronounced like 'jasmine') is a minimalistic JSON parser in C. It can be 62b15cb3dSCy Schuberteasily integrated into resource-limited or embedded projects. 72b15cb3dSCy Schubert 82b15cb3dSCy SchubertYou can find more information about JSON format at [json.org][1] 92b15cb3dSCy Schubert 102b15cb3dSCy SchubertLibrary sources are available at [bitbucket.org/zserge/jsmn][2] 112b15cb3dSCy Schubert 122b15cb3dSCy SchubertThe web page with some information about jsmn can be found at 132b15cb3dSCy Schubert[http://zserge.com/jsmn.html][3] 142b15cb3dSCy Schubert 152b15cb3dSCy SchubertPhilosophy 162b15cb3dSCy Schubert---------- 172b15cb3dSCy Schubert 182b15cb3dSCy SchubertMost JSON parsers offer you a bunch of functions to load JSON data, parse it 192b15cb3dSCy Schubertand extract any value by its name. jsmn proves that checking the correctness of 202b15cb3dSCy Schubertevery JSON packet or allocating temporary objects to store parsed JSON fields 212b15cb3dSCy Schubertoften is an overkill. 222b15cb3dSCy Schubert 232b15cb3dSCy SchubertJSON format itself is extremely simple, so why should we complicate it? 242b15cb3dSCy Schubert 252b15cb3dSCy Schubertjsmn is designed to be **robust** (it should work fine even with erroneous 262b15cb3dSCy Schubertdata), **fast** (it should parse data on the fly), **portable** (no superfluous 272b15cb3dSCy Schubertdependencies or non-standard C extensions). An of course, **simplicity** is a 282b15cb3dSCy Schubertkey feature - simple code style, simple algorithm, simple integration into 292b15cb3dSCy Schubertother projects. 302b15cb3dSCy Schubert 312b15cb3dSCy SchubertFeatures 322b15cb3dSCy Schubert-------- 332b15cb3dSCy Schubert 342b15cb3dSCy Schubert* compatible with C89 352b15cb3dSCy Schubert* no dependencies (even libc!) 362b15cb3dSCy Schubert* highly portable (tested on x86/amd64, ARM, AVR) 372b15cb3dSCy Schubert* about 200 lines of code 382b15cb3dSCy Schubert* extremely small code footprint 392b15cb3dSCy Schubert* API contains only 2 functions 402b15cb3dSCy Schubert* no dynamic memory allocation 412b15cb3dSCy Schubert* incremental single-pass parsing 422b15cb3dSCy Schubert* library code is covered with unit-tests 432b15cb3dSCy Schubert 442b15cb3dSCy SchubertDesign 452b15cb3dSCy Schubert------ 462b15cb3dSCy Schubert 472b15cb3dSCy SchubertThe rudimentary jsmn object is a **token**. Let's consider a JSON string: 482b15cb3dSCy Schubert 492b15cb3dSCy Schubert '{ "name" : "Jack", "age" : 27 }' 502b15cb3dSCy Schubert 512b15cb3dSCy SchubertIt holds the following tokens: 522b15cb3dSCy Schubert 532b15cb3dSCy Schubert* Object: `{ "name" : "Jack", "age" : 27}` (the whole object) 542b15cb3dSCy Schubert* Strings: `"name"`, `"Jack"`, `"age"` (keys and some values) 552b15cb3dSCy Schubert* Number: `27` 562b15cb3dSCy Schubert 572b15cb3dSCy SchubertIn jsmn, tokens do not hold any data, but point to token boundaries in JSON 582b15cb3dSCy Schubertstring instead. In the example above jsmn will create tokens like: Object 592b15cb3dSCy Schubert[0..31], String [3..7], String [12..16], String [20..23], Number [27..29]. 602b15cb3dSCy Schubert 612b15cb3dSCy SchubertEvery jsmn token has a type, which indicates the type of corresponding JSON 622b15cb3dSCy Schuberttoken. jsmn supports the following token types: 632b15cb3dSCy Schubert 642b15cb3dSCy Schubert* Object - a container of key-value pairs, e.g.: 652b15cb3dSCy Schubert `{ "foo":"bar", "x":0.3 }` 662b15cb3dSCy Schubert* Array - a sequence of values, e.g.: 672b15cb3dSCy Schubert `[ 1, 2, 3 ]` 682b15cb3dSCy Schubert* String - a quoted sequence of chars, e.g.: `"foo"` 692b15cb3dSCy Schubert* Primitive - a number, a boolean (`true`, `false`) or `null` 702b15cb3dSCy Schubert 712b15cb3dSCy SchubertBesides start/end positions, jsmn tokens for complex types (like arrays 722b15cb3dSCy Schubertor objects) also contain a number of child items, so you can easily follow 732b15cb3dSCy Schubertobject hierarchy. 742b15cb3dSCy Schubert 752b15cb3dSCy SchubertThis approach provides enough information for parsing any JSON data and makes 762b15cb3dSCy Schubertit possible to use zero-copy techniques. 772b15cb3dSCy Schubert 782b15cb3dSCy SchubertInstall 792b15cb3dSCy Schubert------- 802b15cb3dSCy Schubert 812b15cb3dSCy SchubertTo clone the repository you should have mercurial installed. Just run: 822b15cb3dSCy Schubert 832b15cb3dSCy Schubert $ hg clone http://bitbucket.org/zserge/jsmn jsmn 842b15cb3dSCy Schubert 85*276da39aSCy SchubertRepository layout is simple: jsmn.c and jsmn.h are library files, tests are in 86*276da39aSCy Schubertthe jsmn\_test.c, you will also find README, LICENSE and Makefile files inside. 872b15cb3dSCy Schubert 882b15cb3dSCy SchubertTo build the library, run `make`. It is also recommended to run `make test`. 892b15cb3dSCy SchubertLet me know, if some tests fail. 902b15cb3dSCy Schubert 912b15cb3dSCy SchubertIf build was successful, you should get a `libjsmn.a` library. 922b15cb3dSCy SchubertThe header file you should include is called `"jsmn.h"`. 932b15cb3dSCy Schubert 942b15cb3dSCy SchubertAPI 952b15cb3dSCy Schubert--- 962b15cb3dSCy Schubert 972b15cb3dSCy SchubertToken types are described by `jsmntype_t`: 982b15cb3dSCy Schubert 992b15cb3dSCy Schubert typedef enum { 1002b15cb3dSCy Schubert JSMN_PRIMITIVE = 0, 1012b15cb3dSCy Schubert JSMN_OBJECT = 1, 1022b15cb3dSCy Schubert JSMN_ARRAY = 2, 1032b15cb3dSCy Schubert JSMN_STRING = 3 1042b15cb3dSCy Schubert } jsmntype_t; 1052b15cb3dSCy Schubert 1062b15cb3dSCy Schubert**Note:** Unlike JSON data types, primitive tokens are not divided into 1072b15cb3dSCy Schubertnumbers, booleans and null, because one can easily tell the type using the 1082b15cb3dSCy Schubertfirst character: 1092b15cb3dSCy Schubert 1102b15cb3dSCy Schubert* <code>'t', 'f'</code> - boolean 1112b15cb3dSCy Schubert* <code>'n'</code> - null 1122b15cb3dSCy Schubert* <code>'-', '0'..'9'</code> - number 1132b15cb3dSCy Schubert 1142b15cb3dSCy SchubertToken is an object of `jsmntok_t` type: 1152b15cb3dSCy Schubert 1162b15cb3dSCy Schubert typedef struct { 1172b15cb3dSCy Schubert jsmntype_t type; // Token type 1182b15cb3dSCy Schubert int start; // Token start position 1192b15cb3dSCy Schubert int end; // Token end position 1202b15cb3dSCy Schubert int size; // Number of child (nested) tokens 1212b15cb3dSCy Schubert } jsmntok_t; 1222b15cb3dSCy Schubert 1232b15cb3dSCy Schubert**Note:** string tokens point to the first character after 1242b15cb3dSCy Schubertthe opening quote and the previous symbol before final quote. This was made 1252b15cb3dSCy Schubertto simplify string extraction from JSON data. 1262b15cb3dSCy Schubert 1272b15cb3dSCy SchubertAll job is done by `jsmn_parser` object. You can initialize a new parser using: 1282b15cb3dSCy Schubert 129*276da39aSCy Schubert jsmn_parser parser; 1302b15cb3dSCy Schubert jsmntok_t tokens[10]; 1312b15cb3dSCy Schubert 132*276da39aSCy Schubert jsmn_init(&parser); 133*276da39aSCy Schubert 1342b15cb3dSCy Schubert // js - pointer to JSON string 1352b15cb3dSCy Schubert // tokens - an array of tokens available 1362b15cb3dSCy Schubert // 10 - number of tokens available 137*276da39aSCy Schubert jsmn_parse(&parser, js, tokens, 10); 1382b15cb3dSCy Schubert 139*276da39aSCy SchubertThis will create a parser, and then it tries to parse up to 10 JSON tokens from 140*276da39aSCy Schubertthe `js` string. 1412b15cb3dSCy Schubert 142*276da39aSCy SchubertA non-negative reutrn value of `jsmn_parse` is the number of tokens actually 143*276da39aSCy Schubertused by the parser. 144*276da39aSCy SchubertPassing NULL instead of the tokens array would not store parsing results, but 145*276da39aSCy Schubertinstead the function will return the value of tokens needed to parse the given 146*276da39aSCy Schubertstring. This can be useful if you don't know yet how many tokens to allocate. 147*276da39aSCy Schubert 1482b15cb3dSCy SchubertIf something goes wrong, you will get an error. Error will be one of these: 1492b15cb3dSCy Schubert 1502b15cb3dSCy Schubert* `JSMN_ERROR_INVAL` - bad token, JSON string is corrupted 1512b15cb3dSCy Schubert* `JSMN_ERROR_NOMEM` - not enough tokens, JSON string is too large 1522b15cb3dSCy Schubert* `JSMN_ERROR_PART` - JSON string is too short, expecting more JSON data 1532b15cb3dSCy Schubert 1542b15cb3dSCy SchubertIf you get `JSON_ERROR_NOMEM`, you can re-allocate more tokens and call 1552b15cb3dSCy Schubert`jsmn_parse` once more. If you read json data from the stream, you can 1562b15cb3dSCy Schubertperiodically call `jsmn_parse` and check if return value is `JSON_ERROR_PART`. 1572b15cb3dSCy SchubertYou will get this error until you reach the end of JSON data. 1582b15cb3dSCy Schubert 1592b15cb3dSCy SchubertOther info 1602b15cb3dSCy Schubert---------- 1612b15cb3dSCy Schubert 1622b15cb3dSCy SchubertThis software is distributed under [MIT license](http://www.opensource.org/licenses/mit-license.php), 1632b15cb3dSCy Schubert so feel free to integrate it in your commercial products. 1642b15cb3dSCy Schubert 1652b15cb3dSCy Schubert[1]: http://www.json.org/ 1662b15cb3dSCy Schubert[2]: https://bitbucket.org/zserge/jsmn/wiki/Home 1672b15cb3dSCy Schubert[3]: http://zserge.com/jsmn.html 168