xref: /freebsd/contrib/ntp/libjsmn/README.md (revision b5ff185e19f6013ca565b2a15bc2d6abce933f46)
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