C-based memory friendly JSON parser based on Serge Zaitsev's JSMN (https://bitbucket.org/zserge/jsmn/wiki/Home)
Dependents: _library_jsmn _library_jsmn _library_jsmn
JSMN
jsmn (pronounced like 'jasmine') is a minimalistic JSON parser in C. It can be easily integrated into resource-limited or embedded projects.
You can find more information about JSON format at json.org
Library sources are available at https://bitbucket.org/zserge/jsmn
The web page with some information about jsmn can be found at http://zserge.com/jsmn.html
jsmn.h@2:5167da2fcc4e, 2014-11-17 (annotated)
- Committer:
- yoonghm
- Date:
- Mon Nov 17 16:09:04 2014 +0000
- Revision:
- 2:5167da2fcc4e
- Parent:
- 1:70061827a9c8
Updated copyright information.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
yoonghm | 0:46575249ef23 | 1 | /* C-based low-memory footprint JSON parser for mbed |
yoonghm | 0:46575249ef23 | 2 | * Based on Serge Zaitsev's JSMN https://bitbucket.org/zserge/jsmn/wiki/Home |
yoonghm | 0:46575249ef23 | 3 | * JSMN is distributed under MIT license. |
yoonghm | 0:46575249ef23 | 4 | * |
yoonghm | 2:5167da2fcc4e | 5 | * Copyright (c) 2010 Serge A. Zaitsev |
yoonghm | 0:46575249ef23 | 6 | * Copyright (c) 2014 YoongHM |
yoonghm | 0:46575249ef23 | 7 | * |
yoonghm | 0:46575249ef23 | 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
yoonghm | 0:46575249ef23 | 9 | * of this software and associated documentation files (the "Software"), to deal |
yoonghm | 0:46575249ef23 | 10 | * in the Software without restriction, including without limitation the rights |
yoonghm | 0:46575249ef23 | 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
yoonghm | 0:46575249ef23 | 12 | * copies of the Software, and to permit persons to whom the Software is |
yoonghm | 0:46575249ef23 | 13 | * furnished to do so, subject to the following conditions: |
yoonghm | 0:46575249ef23 | 14 | * |
yoonghm | 0:46575249ef23 | 15 | * The above copyright notice and this permission notice shall be included in |
yoonghm | 0:46575249ef23 | 16 | * all copies or substantial portions of the Software. |
yoonghm | 0:46575249ef23 | 17 | * |
yoonghm | 0:46575249ef23 | 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
yoonghm | 0:46575249ef23 | 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
yoonghm | 0:46575249ef23 | 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
yoonghm | 0:46575249ef23 | 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
yoonghm | 0:46575249ef23 | 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
yoonghm | 0:46575249ef23 | 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
yoonghm | 0:46575249ef23 | 24 | * THE SOFTWARE. |
yoonghm | 0:46575249ef23 | 25 | */ |
yoonghm | 0:46575249ef23 | 26 | |
yoonghm | 0:46575249ef23 | 27 | #ifndef MBED_JSMN_H |
yoonghm | 0:46575249ef23 | 28 | #define MBED_JSMN_H |
yoonghm | 0:46575249ef23 | 29 | |
yoonghm | 0:46575249ef23 | 30 | /** |
yoonghm | 0:46575249ef23 | 31 | * A c-based low-memory low-memory footprint JSON parser for mbed. |
yoonghm | 0:46575249ef23 | 32 | * |
yoonghm | 0:46575249ef23 | 33 | * The code is based on Serge Zaitsev's JSMN on |
yoonghm | 0:46575249ef23 | 34 | * https://bitbucket.org/zserge/jsmn/wiki/Home |
yoonghm | 0:46575249ef23 | 35 | * |
yoonghm | 0:46575249ef23 | 36 | * @code |
yoonghm | 0:46575249ef23 | 37 | *#include "mbed.h" |
yoonghm | 0:46575249ef23 | 38 | * |
yoonghm | 0:46575249ef23 | 39 | *#include "jsmn.h" |
yoonghm | 0:46575249ef23 | 40 | * |
yoonghm | 0:46575249ef23 | 41 | *#define MAXTOKEN 64 |
yoonghm | 0:46575249ef23 | 42 | * |
yoonghm | 0:46575249ef23 | 43 | *const char *jsmn_type_str[] = { |
yoonghm | 0:46575249ef23 | 44 | * "PRIMITIVE", |
yoonghm | 0:46575249ef23 | 45 | * "OBJECT", |
yoonghm | 1:70061827a9c8 | 46 | * "ARRAY", |
yoonghm | 0:46575249ef23 | 47 | * "STRING" |
yoonghm | 0:46575249ef23 | 48 | *}; |
yoonghm | 0:46575249ef23 | 49 | * |
yoonghm | 0:46575249ef23 | 50 | *int main() |
yoonghm | 0:46575249ef23 | 51 | *{ |
yoonghm | 0:46575249ef23 | 52 | * const char *js; // Pointer to json string |
yoonghm | 0:46575249ef23 | 53 | * int r; // Number of token parsed |
yoonghm | 0:46575249ef23 | 54 | * jsmn_parser p; // jsmn parser |
yoonghm | 0:46575249ef23 | 55 | * jsmntok_t t[MAXTOKEN]; // Parsed token |
yoonghm | 0:46575249ef23 | 56 | * |
yoonghm | 0:46575249ef23 | 57 | * // JSON may contain multibyte characters or encoded unicode in |
yoonghm | 0:46575249ef23 | 58 | * // \uXXXX format. |
yoonghm | 0:46575249ef23 | 59 | * // mbed compiler may complain "invalid multibyte characters ...". |
yoonghm | 0:46575249ef23 | 60 | * js = |
yoonghm | 0:46575249ef23 | 61 | *"{" |
yoonghm | 0:46575249ef23 | 62 | *" \"menu\":" |
yoonghm | 0:46575249ef23 | 63 | *" {" |
yoonghm | 0:46575249ef23 | 64 | *" \"id\": 1234," |
yoonghm | 0:46575249ef23 | 65 | *" \"group\": \"File\"," |
yoonghm | 0:46575249ef23 | 66 | *" \"popup\":" |
yoonghm | 0:46575249ef23 | 67 | *" {" |
yoonghm | 0:46575249ef23 | 68 | *" \"menuitem\":" |
yoonghm | 0:46575249ef23 | 69 | *" [" |
yoonghm | 0:46575249ef23 | 70 | *" {\"value\": true, \"onclick\" : \"বিশাল\"}," |
yoonghm | 0:46575249ef23 | 71 | *" {\"value\": false, 0x1328 : \"groß\"}," |
yoonghm | 0:46575249ef23 | 72 | *" {\"value\": null, \"15\u00f8C\": \"3\u0111\"}," |
yoonghm | 0:46575249ef23 | 73 | *" {\"value\": \"測試\", -12.34 : 99}" |
yoonghm | 0:46575249ef23 | 74 | *" ]" |
yoonghm | 0:46575249ef23 | 75 | *" }" |
yoonghm | 0:46575249ef23 | 76 | *" }" |
yoonghm | 0:46575249ef23 | 77 | *"}"; |
yoonghm | 0:46575249ef23 | 78 | * |
yoonghm | 0:46575249ef23 | 79 | * jsmn_init(&p); |
yoonghm | 0:46575249ef23 | 80 | * r = jsmn_parse(&p, js, strlen(js), t, MAXTOKEN); |
yoonghm | 0:46575249ef23 | 81 | * |
yoonghm | 0:46575249ef23 | 82 | * printf("Parsed %d tokens\n", r); |
yoonghm | 0:46575249ef23 | 83 | * |
yoonghm | 0:46575249ef23 | 84 | * printf(" TYPE START END SIZE PAR\n"); |
yoonghm | 0:46575249ef23 | 85 | * printf(" ---------- ----- ---- ---- ---\n"); |
yoonghm | 0:46575249ef23 | 86 | * |
yoonghm | 0:46575249ef23 | 87 | * char ch; |
yoonghm | 0:46575249ef23 | 88 | * jsmntok_t at; // A token for general use |
yoonghm | 0:46575249ef23 | 89 | * for (int i = 0; i < r; i++) |
yoonghm | 0:46575249ef23 | 90 | * { |
yoonghm | 0:46575249ef23 | 91 | * at = t[i]; |
yoonghm | 0:46575249ef23 | 92 | * printf("Token %2d = %-10.10s (%4d - %4d, %3d, %2d) --> ", |
yoonghm | 0:46575249ef23 | 93 | * i, jsmn_type_str[at.type], |
yoonghm | 0:46575249ef23 | 94 | * at.start, at.end, |
yoonghm | 0:46575249ef23 | 95 | * at.size, at.parent); |
yoonghm | 0:46575249ef23 | 96 | * |
yoonghm | 0:46575249ef23 | 97 | * switch (at.type) |
yoonghm | 0:46575249ef23 | 98 | * { |
yoonghm | 0:46575249ef23 | 99 | * case JSMN_STRING: |
yoonghm | 0:46575249ef23 | 100 | * printf("%-10.*s\n", at.end - at.start + 2, js + at.start - 1); |
yoonghm | 0:46575249ef23 | 101 | * break; |
yoonghm | 0:46575249ef23 | 102 | * |
yoonghm | 0:46575249ef23 | 103 | * case JSMN_PRIMITIVE: |
yoonghm | 0:46575249ef23 | 104 | * ch = *(js + at.start); |
yoonghm | 0:46575249ef23 | 105 | * |
yoonghm | 0:46575249ef23 | 106 | * if (isdigit(ch) || ch == '-') |
yoonghm | 0:46575249ef23 | 107 | * printf("%-10.*s\n", at.end - at.start, js + at.start); |
yoonghm | 0:46575249ef23 | 108 | * else if (tolower(ch) == 'n') |
yoonghm | 0:46575249ef23 | 109 | * printf("null\n"); |
yoonghm | 0:46575249ef23 | 110 | * else if (tolower(ch) == 't') |
yoonghm | 0:46575249ef23 | 111 | * printf("true\n"); |
yoonghm | 0:46575249ef23 | 112 | * else if (tolower(ch) == 'f') |
yoonghm | 0:46575249ef23 | 113 | * printf("false\n"); |
yoonghm | 0:46575249ef23 | 114 | * break; |
yoonghm | 0:46575249ef23 | 115 | * |
yoonghm | 0:46575249ef23 | 116 | * default: |
yoonghm | 0:46575249ef23 | 117 | * printf("\n"); |
yoonghm | 0:46575249ef23 | 118 | * break; |
yoonghm | 0:46575249ef23 | 119 | * } |
yoonghm | 0:46575249ef23 | 120 | * } |
yoonghm | 0:46575249ef23 | 121 | * |
yoonghm | 0:46575249ef23 | 122 | * while (1) |
yoonghm | 0:46575249ef23 | 123 | * ; |
yoonghm | 0:46575249ef23 | 124 | *} |
yoonghm | 0:46575249ef23 | 125 | * @endcode |
yoonghm | 0:46575249ef23 | 126 | */ |
yoonghm | 0:46575249ef23 | 127 | |
yoonghm | 0:46575249ef23 | 128 | /** jsmntype_t - JSON type recongized by JSMN. |
yoonghm | 0:46575249ef23 | 129 | * There are |
yoonghm | 0:46575249ef23 | 130 | * - Primitive: number, boolean (true/false) or null |
yoonghm | 0:46575249ef23 | 131 | * - Object |
yoonghm | 0:46575249ef23 | 132 | * - Array |
yoonghm | 0:46575249ef23 | 133 | * - String |
yoonghm | 0:46575249ef23 | 134 | */ |
yoonghm | 0:46575249ef23 | 135 | typedef enum { |
yoonghm | 0:46575249ef23 | 136 | JSMN_PRIMITIVE = 0, |
yoonghm | 0:46575249ef23 | 137 | JSMN_OBJECT = 1, |
yoonghm | 0:46575249ef23 | 138 | JSMN_ARRAY = 2, |
yoonghm | 0:46575249ef23 | 139 | JSMN_STRING = 3, |
yoonghm | 0:46575249ef23 | 140 | JSMN_INVALID = 4 |
yoonghm | 0:46575249ef23 | 141 | } jsmntype_t; |
yoonghm | 0:46575249ef23 | 142 | |
yoonghm | 0:46575249ef23 | 143 | |
yoonghm | 0:46575249ef23 | 144 | /** Error message return by JSMN API |
yoonghm | 0:46575249ef23 | 145 | * |
yoonghm | 0:46575249ef23 | 146 | */ |
yoonghm | 0:46575249ef23 | 147 | #define JSMN_ERR_OKAY 0 /* No problem */ |
yoonghm | 0:46575249ef23 | 148 | #define JSMN_ERR_NOMEM -1 /* Not enough tokens were provided */ |
yoonghm | 0:46575249ef23 | 149 | #define JSMN_ERR_INVAL -2 /* Invalid character inside JSON string */ |
yoonghm | 0:46575249ef23 | 150 | #define JSMN_ERR_PART -3 /* Incomplete JSON packet */ |
yoonghm | 0:46575249ef23 | 151 | |
yoonghm | 0:46575249ef23 | 152 | |
yoonghm | 0:46575249ef23 | 153 | /** jsmntok_t - JSON token structure. |
yoonghm | 0:46575249ef23 | 154 | * |
yoonghm | 0:46575249ef23 | 155 | * It is a c structure that contained parsed JSON token. |
yoonghm | 0:46575249ef23 | 156 | * |
yoonghm | 0:46575249ef23 | 157 | * @param type type (primitive, object, array, string) |
yoonghm | 0:46575249ef23 | 158 | * @param start start position in JSON data string, excl " if is a string |
yoonghm | 0:46575249ef23 | 159 | * @param end end position in JSON data string, incl " if is a string |
yoonghm | 0:46575249ef23 | 160 | * @param size number of token directly under it |
yoonghm | 0:46575249ef23 | 161 | * @param parent link to its direct parent token number |
yoonghm | 0:46575249ef23 | 162 | */ |
yoonghm | 0:46575249ef23 | 163 | typedef struct { |
yoonghm | 0:46575249ef23 | 164 | jsmntype_t type; |
yoonghm | 0:46575249ef23 | 165 | int start; /* Token's start pos;excl " if is a str */ |
yoonghm | 0:46575249ef23 | 166 | int end; /* Token's last pos;incl " if is a str */ |
yoonghm | 0:46575249ef23 | 167 | int size; /* Number of token directly under it */ |
yoonghm | 0:46575249ef23 | 168 | int parent; /* Nth-token which is its direct parent */ |
yoonghm | 0:46575249ef23 | 169 | } jsmntok_t; |
yoonghm | 0:46575249ef23 | 170 | |
yoonghm | 0:46575249ef23 | 171 | |
yoonghm | 0:46575249ef23 | 172 | /** JSON parser - JSON parser structure. |
yoonghm | 0:46575249ef23 | 173 | * |
yoonghm | 0:46575249ef23 | 174 | * Contains an array of token blocks available. Also stores |
yoonghm | 0:46575249ef23 | 175 | * the string being parsed now and current position in that string |
yoonghm | 0:46575249ef23 | 176 | */ |
yoonghm | 0:46575249ef23 | 177 | typedef struct { |
yoonghm | 0:46575249ef23 | 178 | unsigned int pos; /* offset in the JSON string */ |
yoonghm | 0:46575249ef23 | 179 | unsigned int toknext; /* next token to allocate */ |
yoonghm | 0:46575249ef23 | 180 | int toksuper; /* superior token node, (parent or array)*/ |
yoonghm | 0:46575249ef23 | 181 | } jsmn_parser; |
yoonghm | 0:46575249ef23 | 182 | |
yoonghm | 0:46575249ef23 | 183 | |
yoonghm | 0:46575249ef23 | 184 | /** Initialize jsmn_parser structure for a new JSON parsing |
yoonghm | 0:46575249ef23 | 185 | * |
yoonghm | 0:46575249ef23 | 186 | * @param *parser jsmn_parser structure |
yoonghm | 0:46575249ef23 | 187 | */ |
yoonghm | 0:46575249ef23 | 188 | void |
yoonghm | 0:46575249ef23 | 189 | jsmn_init |
yoonghm | 0:46575249ef23 | 190 | (jsmn_parser *parser |
yoonghm | 0:46575249ef23 | 191 | ); |
yoonghm | 0:46575249ef23 | 192 | |
yoonghm | 0:46575249ef23 | 193 | /** Parse a given JSON data string into array of jsmntok_t tokens. |
yoonghm | 0:46575249ef23 | 194 | * |
yoonghm | 0:46575249ef23 | 195 | * @param *parser jsmn_parser structure |
yoonghm | 0:46575249ef23 | 196 | * @param *js JSON data string |
yoonghm | 0:46575249ef23 | 197 | * @param len string length of *js |
yoonghm | 0:46575249ef23 | 198 | * @param *tokens tokens to hold the parsed data |
yoonghm | 0:46575249ef23 | 199 | */ |
yoonghm | 0:46575249ef23 | 200 | int |
yoonghm | 0:46575249ef23 | 201 | jsmn_parse |
yoonghm | 0:46575249ef23 | 202 | (jsmn_parser *parser |
yoonghm | 0:46575249ef23 | 203 | ,const char *js |
yoonghm | 0:46575249ef23 | 204 | ,size_t len |
yoonghm | 0:46575249ef23 | 205 | ,jsmntok_t *tokens |
yoonghm | 0:46575249ef23 | 206 | ,unsigned int num_tokens |
yoonghm | 0:46575249ef23 | 207 | ); |
yoonghm | 0:46575249ef23 | 208 | |
yoonghm | 0:46575249ef23 | 209 | |
yoonghm | 0:46575249ef23 | 210 | #endif // JSMN_H |