json.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  1. #include "jsmn.h"
  2. #include "../libnetdata.h"
  3. #include "json.h"
  4. #include "libnetdata/libnetdata.h"
  5. #include "../../health/health.h"
  6. #define JSON_TOKENS 1024
  7. int json_tokens = JSON_TOKENS;
  8. /**
  9. * Json Tokenise
  10. *
  11. * Map the string given inside tokens.
  12. *
  13. * @param js is the string used to create the tokens
  14. * @param len is the string length
  15. * @param count the number of tokens present in the string
  16. *
  17. * @return it returns the json parsed in tokens
  18. */
  19. #ifdef ENABLE_JSONC
  20. json_object *json_tokenise(char *js) {
  21. if(!js) {
  22. error("JSON: json string is empty.");
  23. return NULL;
  24. }
  25. json_object *token = json_tokener_parse(js);
  26. if(!token) {
  27. error("JSON: Invalid json string.");
  28. return NULL;
  29. }
  30. return token;
  31. }
  32. #else
  33. jsmntok_t *json_tokenise(char *js, size_t len, size_t *count)
  34. {
  35. int n = json_tokens;
  36. if(!js || !len) {
  37. error("JSON: json string is empty.");
  38. return NULL;
  39. }
  40. jsmn_parser parser;
  41. jsmn_init(&parser);
  42. jsmntok_t *tokens = mallocz(sizeof(jsmntok_t) * n);
  43. if(!tokens) return NULL;
  44. int ret = jsmn_parse(&parser, js, len, tokens, n);
  45. while (ret == JSMN_ERROR_NOMEM) {
  46. n *= 2;
  47. jsmntok_t *new = reallocz(tokens, sizeof(jsmntok_t) * n);
  48. if(!new) {
  49. freez(tokens);
  50. return NULL;
  51. }
  52. tokens = new;
  53. ret = jsmn_parse(&parser, js, len, tokens, n);
  54. }
  55. if (ret == JSMN_ERROR_INVAL) {
  56. error("JSON: Invalid json string.");
  57. freez(tokens);
  58. return NULL;
  59. }
  60. else if (ret == JSMN_ERROR_PART) {
  61. error("JSON: Truncated JSON string.");
  62. freez(tokens);
  63. return NULL;
  64. }
  65. if(count) *count = (size_t)ret;
  66. if(json_tokens < n) json_tokens = n;
  67. return tokens;
  68. }
  69. #endif
  70. /**
  71. * Callback Print
  72. *
  73. * Set callback print case necessary and wrinte an information inside a buffer to write in the log.
  74. *
  75. * @param e a pointer for a structure that has the complete information about json structure.
  76. *
  77. * @return It always return 0
  78. */
  79. int json_callback_print(JSON_ENTRY *e)
  80. {
  81. BUFFER *wb=buffer_create(300);
  82. buffer_sprintf(wb,"%s = ", e->name);
  83. char txt[50];
  84. switch(e->type) {
  85. case JSON_OBJECT:
  86. e->callback_function = json_callback_print;
  87. buffer_strcat(wb,"OBJECT");
  88. break;
  89. case JSON_ARRAY:
  90. e->callback_function = json_callback_print;
  91. sprintf(txt,"ARRAY[%lu]", e->data.items);
  92. buffer_strcat(wb, txt);
  93. break;
  94. case JSON_STRING:
  95. buffer_strcat(wb, e->data.string);
  96. break;
  97. case JSON_NUMBER:
  98. sprintf(txt, NETDATA_DOUBLE_FORMAT_AUTO, e->data.number);
  99. buffer_strcat(wb,txt);
  100. break;
  101. case JSON_BOOLEAN:
  102. buffer_strcat(wb, e->data.boolean?"TRUE":"FALSE");
  103. break;
  104. case JSON_NULL:
  105. buffer_strcat(wb,"NULL");
  106. break;
  107. }
  108. info("JSON: %s", buffer_tostring(wb));
  109. buffer_free(wb);
  110. return 0;
  111. }
  112. /**
  113. * JSONC Set String
  114. *
  115. * Set the string value of the structure JSON_ENTRY.
  116. *
  117. * @param e the output structure
  118. */
  119. static inline void json_jsonc_set_string(JSON_ENTRY *e,char *key,const char *value) {
  120. size_t len = strlen(key);
  121. if(len > JSON_NAME_LEN)
  122. len = JSON_NAME_LEN;
  123. e->type = JSON_STRING;
  124. memcpy(e->name,key,len);
  125. e->name[len] = 0x00;
  126. e->data.string = (char *) value;
  127. }
  128. #ifdef ENABLE_JSONC
  129. /**
  130. * JSONC set Boolean
  131. *
  132. * Set the boolean value of the structure JSON_ENTRY
  133. *
  134. * @param e the output structure
  135. * @param value the input value
  136. */
  137. static inline void json_jsonc_set_boolean(JSON_ENTRY *e,int value) {
  138. e->type = JSON_BOOLEAN;
  139. e->data.boolean = value;
  140. }
  141. static inline void json_jsonc_set_integer(JSON_ENTRY *e, char *key, int64_t value) {
  142. size_t len = strlen(key);
  143. if(len > JSON_NAME_LEN)
  144. len = JSON_NAME_LEN;
  145. e->type = JSON_NUMBER;
  146. memcpy(e->name, key, len);
  147. e->name[len] = 0;
  148. e->data.number = (NETDATA_DOUBLE)value;
  149. }
  150. /**
  151. * Parse Array
  152. *
  153. * Parse the array object.
  154. *
  155. * @param ptr the pointer for the object that we will parse.
  156. * @param callback_data additional data to be used together the callback function
  157. * @param callback_function function used to create a silencer.
  158. */
  159. static inline void json_jsonc_parse_array(json_object *ptr, void *callback_data,int (*callback_function)(struct json_entry *)) {
  160. int end = json_object_array_length(ptr);
  161. JSON_ENTRY e;
  162. if(end) {
  163. int i;
  164. i = 0;
  165. enum json_type type;
  166. do {
  167. json_object *jvalue = json_object_array_get_idx(ptr, i);
  168. if(jvalue) {
  169. e.callback_data = callback_data;
  170. e.type = JSON_OBJECT;
  171. callback_function(&e);
  172. json_object_object_foreach(jvalue, key, val) {
  173. type = json_object_get_type(val);
  174. if (type == json_type_array) {
  175. e.type = JSON_ARRAY;
  176. json_jsonc_parse_array(val, callback_data, callback_function);
  177. } else if (type == json_type_object) {
  178. json_walk(val,callback_data,callback_function);
  179. } else if (type == json_type_string) {
  180. json_jsonc_set_string(&e,key,json_object_get_string(val));
  181. callback_function(&e);
  182. } else if (type == json_type_boolean) {
  183. json_jsonc_set_boolean(&e,json_object_get_boolean(val));
  184. callback_function(&e);
  185. }
  186. }
  187. }
  188. } while (++i < end);
  189. }
  190. }
  191. #else
  192. /**
  193. * Walk string
  194. *
  195. * Set JSON_ENTRY to string and map the values from jsmntok_t.
  196. *
  197. * @param js the original string
  198. * @param t the tokens
  199. * @param start the first position
  200. * @param e the output structure.
  201. *
  202. * @return It always return 1
  203. */
  204. size_t json_walk_string(char *js, jsmntok_t *t, size_t start, JSON_ENTRY *e)
  205. {
  206. char old = js[t[start].end];
  207. js[t[start].end] = '\0';
  208. e->original_string = &js[t[start].start];
  209. e->type = JSON_STRING;
  210. e->data.string = e->original_string;
  211. if(e->callback_function) e->callback_function(e);
  212. js[t[start].end] = old;
  213. return 1;
  214. }
  215. /**
  216. * Walk Primitive
  217. *
  218. * Define the data type of the string
  219. *
  220. * @param js the original string
  221. * @param t the tokens
  222. * @param start the first position
  223. * @param e the output structure.
  224. *
  225. * @return It always return 1
  226. */
  227. size_t json_walk_primitive(char *js, jsmntok_t *t, size_t start, JSON_ENTRY *e)
  228. {
  229. char old = js[t[start].end];
  230. js[t[start].end] = '\0';
  231. e->original_string = &js[t[start].start];
  232. switch(e->original_string[0]) {
  233. case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7':
  234. case '8': case '9': case '-': case '.':
  235. e->type = JSON_NUMBER;
  236. e->data.number = strtold(e->original_string, NULL);
  237. break;
  238. case 't': case 'T':
  239. e->type = JSON_BOOLEAN;
  240. e->data.boolean = 1;
  241. break;
  242. case 'f': case 'F':
  243. e->type = JSON_BOOLEAN;
  244. e->data.boolean = 0;
  245. break;
  246. case 'n': case 'N':
  247. default:
  248. e->type = JSON_NULL;
  249. break;
  250. }
  251. if(e->callback_function) e->callback_function(e);
  252. js[t[start].end] = old;
  253. return 1;
  254. }
  255. /**
  256. * Array
  257. *
  258. * Measure the array length
  259. *
  260. * @param js the original string
  261. * @param t the tokens
  262. * @param nest the length of structure t
  263. * @param start the first position
  264. * @param e the structure with values and callback to be used inside the function.
  265. *
  266. * @return It returns the array length
  267. */
  268. size_t json_walk_array(char *js, jsmntok_t *t, size_t nest, size_t start, JSON_ENTRY *e)
  269. {
  270. JSON_ENTRY ne;
  271. char old = js[t[start].end];
  272. js[t[start].end] = '\0';
  273. ne.original_string = &js[t[start].start];
  274. memcpy(&ne, e, sizeof(JSON_ENTRY));
  275. ne.type = JSON_ARRAY;
  276. ne.data.items = t[start].size;
  277. ne.callback_function = e->callback_function;
  278. ne.name[0]='\0';
  279. ne.fullname[0]='\0';
  280. if(e->callback_function) e->callback_function(&ne);
  281. js[t[start].end] = old;
  282. size_t i, init = start, size = t[start].size;
  283. start++;
  284. for(i = 0; i < size ; i++) {
  285. ne.pos = i;
  286. if (strlen(e->name) > JSON_NAME_LEN - 24 || strlen(e->fullname) > JSON_FULLNAME_LEN -24) {
  287. info("JSON: JSON walk_array ignoring element with name:%s fullname:%s",e->name, e->fullname);
  288. continue;
  289. }
  290. snprintfz(ne.name, JSON_NAME_LEN, "%s[%lu]", e->name, i);
  291. snprintfz(ne.fullname, JSON_FULLNAME_LEN, "%s[%lu]", e->fullname, i);
  292. switch(t[start].type) {
  293. case JSMN_PRIMITIVE:
  294. start += json_walk_primitive(js, t, start, &ne);
  295. break;
  296. case JSMN_OBJECT:
  297. start += json_walk_object(js, t, nest + 1, start, &ne);
  298. break;
  299. case JSMN_ARRAY:
  300. start += json_walk_array(js, t, nest + 1, start, &ne);
  301. break;
  302. case JSMN_STRING:
  303. start += json_walk_string(js, t, start, &ne);
  304. break;
  305. }
  306. }
  307. return start - init;
  308. }
  309. /**
  310. * Object
  311. *
  312. * Measure the Object length
  313. *
  314. * @param js the original string
  315. * @param t the tokens
  316. * @param nest the length of structure t
  317. * @param start the first position
  318. * @param e the output structure.
  319. *
  320. * @return It returns the Object length
  321. */
  322. size_t json_walk_object(char *js, jsmntok_t *t, size_t nest, size_t start, JSON_ENTRY *e)
  323. {
  324. JSON_ENTRY ne = {
  325. .name = "",
  326. .fullname = "",
  327. .callback_data = NULL,
  328. .callback_function = NULL
  329. };
  330. char old = js[t[start].end];
  331. js[t[start].end] = '\0';
  332. ne.original_string = &js[t[start].start];
  333. memcpy(&ne, e, sizeof(JSON_ENTRY));
  334. ne.type = JSON_OBJECT;
  335. ne.callback_function = e->callback_function;
  336. if(e->callback_function) e->callback_function(&ne);
  337. js[t[start].end] = old;
  338. int key = 1;
  339. size_t i, init = start, size = t[start].size;
  340. start++;
  341. for(i = 0; i < size ; i++) {
  342. switch(t[start].type) {
  343. case JSMN_PRIMITIVE:
  344. start += json_walk_primitive(js, t, start, &ne);
  345. key = 1;
  346. break;
  347. case JSMN_OBJECT:
  348. start += json_walk_object(js, t, nest + 1, start, &ne);
  349. key = 1;
  350. break;
  351. case JSMN_ARRAY:
  352. start += json_walk_array(js, t, nest + 1, start, &ne);
  353. key = 1;
  354. break;
  355. case JSMN_STRING:
  356. default:
  357. if(key) {
  358. int len = t[start].end - t[start].start;
  359. if (unlikely(len>JSON_NAME_LEN)) len=JSON_NAME_LEN;
  360. strncpy(ne.name, &js[t[start].start], len);
  361. ne.name[len] = '\0';
  362. len=strlen(e->fullname) + strlen(e->fullname[0]?".":"") + strlen(ne.name);
  363. char *c = mallocz((len+1)*sizeof(char));
  364. sprintf(c,"%s%s%s", e->fullname, e->fullname[0]?".":"", ne.name);
  365. if (unlikely(len>JSON_FULLNAME_LEN)) len=JSON_FULLNAME_LEN;
  366. strncpy(ne.fullname, c, len);
  367. freez(c);
  368. start++;
  369. key = 0;
  370. }
  371. else {
  372. start += json_walk_string(js, t, start, &ne);
  373. key = 1;
  374. }
  375. break;
  376. }
  377. }
  378. return start - init;
  379. }
  380. #endif
  381. /**
  382. * Tree
  383. *
  384. * Call the correct walk function according its type.
  385. *
  386. * @param t the json object to work
  387. * @param callback_data additional data to be used together the callback function
  388. * @param callback_function function used to create a silencer.
  389. *
  390. * @return It always return 1
  391. */
  392. #ifdef ENABLE_JSONC
  393. size_t json_walk(json_object *t, void *callback_data, int (*callback_function)(struct json_entry *)) {
  394. JSON_ENTRY e;
  395. e.callback_data = callback_data;
  396. enum json_type type;
  397. json_object_object_foreach(t, key, val) {
  398. type = json_object_get_type(val);
  399. if (type == json_type_array) {
  400. e.type = JSON_ARRAY;
  401. json_jsonc_parse_array(val,NULL,health_silencers_json_read_callback);
  402. } else if (type == json_type_object) {
  403. e.type = JSON_OBJECT;
  404. } else if (type == json_type_string) {
  405. json_jsonc_set_string(&e,key,json_object_get_string(val));
  406. callback_function(&e);
  407. } else if (type == json_type_boolean) {
  408. json_jsonc_set_boolean(&e,json_object_get_boolean(val));
  409. callback_function(&e);
  410. } else if (type == json_type_int) {
  411. json_jsonc_set_integer(&e,key,json_object_get_int64(val));
  412. callback_function(&e);
  413. }
  414. }
  415. return 1;
  416. }
  417. #else
  418. /**
  419. * Tree
  420. *
  421. * Call the correct walk function according its type.
  422. *
  423. * @param js the original string
  424. * @param t the tokens
  425. * @param callback_data additional data to be used together the callback function
  426. * @param callback_function function used to create a silencer.
  427. *
  428. * @return It always return 1
  429. */
  430. size_t json_walk_tree(char *js, jsmntok_t *t, void *callback_data, int (*callback_function)(struct json_entry *))
  431. {
  432. JSON_ENTRY e = {
  433. .name = "",
  434. .fullname = "",
  435. .callback_data = callback_data,
  436. .callback_function = callback_function
  437. };
  438. switch (t[0].type) {
  439. case JSMN_OBJECT:
  440. e.type = JSON_OBJECT;
  441. json_walk_object(js, t, 0, 0, &e);
  442. break;
  443. case JSMN_ARRAY:
  444. e.type = JSON_ARRAY;
  445. json_walk_array(js, t, 0, 0, &e);
  446. break;
  447. case JSMN_PRIMITIVE:
  448. case JSMN_STRING:
  449. break;
  450. }
  451. return 1;
  452. }
  453. #endif
  454. /**
  455. * JSON Parse
  456. *
  457. * Parse the json message with the callback function
  458. *
  459. * @param js the string that the callback function will parse
  460. * @param callback_data additional data to be used together the callback function
  461. * @param callback_function function used to create a silencer.
  462. *
  463. * @return JSON_OK case everything happened as expected, JSON_CANNOT_PARSE case there were errors in the
  464. * parsing process and JSON_CANNOT_DOWNLOAD case the string given(js) is NULL.
  465. */
  466. int json_parse(char *js, void *callback_data, int (*callback_function)(JSON_ENTRY *))
  467. {
  468. if(js) {
  469. #ifdef ENABLE_JSONC
  470. json_object *tokens = json_tokenise(js);
  471. #else
  472. size_t count;
  473. jsmntok_t *tokens = json_tokenise(js, strlen(js), &count);
  474. #endif
  475. if(tokens) {
  476. #ifdef ENABLE_JSONC
  477. json_walk(tokens, callback_data, callback_function);
  478. json_object_put(tokens);
  479. #else
  480. json_walk_tree(js, tokens, callback_data, callback_function);
  481. freez(tokens);
  482. #endif
  483. return JSON_OK;
  484. }
  485. return JSON_CANNOT_PARSE;
  486. }
  487. return JSON_CANNOT_DOWNLOAD;
  488. }
  489. /*
  490. int json_test(char *str)
  491. {
  492. return json_parse(str, NULL, json_callback_print);
  493. }
  494. */