json_t *json_path_get(const json_t *json, const char *path) { static const char array_open = '['; static const char *path_delims = ".[", *array_close = "]"; const json_t *cursor; char *token, *buf, *peek, *endptr, delim = '\0'; const char *expect; if (!json || !path) return NULL; else buf = jsonp_strdup(path); peek = buf; token = buf; cursor = json; expect = path_delims; if (*token == array_open) { expect = array_close; token++; } while (peek && *peek && cursor) { char *last_peek = peek; peek = strpbrk(peek, expect); if (peek) { if (!token && peek != last_peek) goto fail; delim = *peek; *peek++ = '\0'; } else if (expect != path_delims || !token) { goto fail; } if (expect == path_delims) { if (token) { cursor = json_object_get(cursor, token); } expect = (delim == array_open ? array_close : path_delims); token = peek; } else if (expect == array_close) { size_t index = strtol(token, &endptr, 0); if (*endptr) goto fail; cursor = json_array_get(cursor, index); token = NULL; expect = path_delims; } else { goto fail; } } jsonp_free(buf); return (json_t *)cursor; fail: jsonp_free(buf); return NULL; }
int json_string_set_nocheck(json_t *json, const char *value) { char *dup; json_string_t *string; if(!json_is_string(json) || !value) return -1; dup = jsonp_strdup(value); if(!dup) return -1; string = json_to_string(json); jsonp_free(string->value); string->value = dup; return 0; }
json_t *json_string_nocheck(const char *value) { json_string_t *string; if(!value) return NULL; string = (json_string_t *) jsonp_malloc(sizeof(json_string_t)); if(!string) return NULL; json_init(&string->json, JSON_STRING); string->value = jsonp_strdup(value); if(!string->value) { jsonp_free(string); return NULL; } return &string->json; }
int json_path_set(json_t *json, const char *path, json_t *value, unsigned int append) { static const char array_open = '['; static const char object_delim = '.'; static const char *path_delims = ".["; static const char *array_close = "]"; json_t *cursor, *parent = NULL; char *token, *buf = NULL, *peek, delim = '\0'; const char *expect; int index_saved = -1; if (!json || !path || !value) { ERR("invalid arguments\n"); goto fail; } else { buf = jsonp_strdup(path); } peek = buf; token = buf; cursor = json; expect = path_delims; if (*token == array_open) { expect = array_close; token++; } while (peek && *peek && cursor) { char *last_peek = peek; peek = strpbrk(last_peek, expect); if (peek) { if (!token && peek != last_peek) { ERR("unexpected trailing chars in JSON path at pos %zu\n", last_peek - buf); goto fail; } delim = *peek; *peek++ = '\0'; } else { // end of path if (expect == path_delims) { break; } else { ERR("missing ']' at pos %zu\n", peek - buf); goto fail; } } if (expect == path_delims) { if (token) { if (token[0] == '\0') { ERR("empty token at pos %zu\n", peek - buf); goto fail; } parent = cursor; cursor = json_object_get(parent, token); if (!cursor) { if (!json_is_object(parent)) { ERR("object expected at pos %zu\n", peek - buf); goto fail; } if (delim == object_delim) { cursor = json_object(); json_object_set_new(parent, token, cursor); } else { ERR("new array is not allowed at pos %zu\n", peek - buf); goto fail; } } } expect = (delim == array_open ? array_close : path_delims); token = peek; } else if (expect == array_close) { char *endptr; size_t index; parent = cursor; if (!json_is_array(parent)) { ERR("array expected at pos %zu\n", peek - buf); goto fail; } index = strtol(token, &endptr, 0); if (*endptr) { ERR("invalid array index at pos %zu\n", peek - buf); goto fail; } cursor = json_array_get(parent, index); if (!cursor) { ERR("array index out of bound at pos %zu\n", peek - buf); goto fail; } index_saved = index; token = NULL; expect = path_delims; } else { ERR("fatal JSON error at pos %zu\n", peek - buf); goto fail; } } if (token && append) { if(strlen(token) > 0) { json_t* tmp = json_object_get(cursor, token); if(json_is_array(tmp)) { json_array_append(tmp, value); json_object_set(cursor, token, tmp); } else if(json_is_object(tmp) && json_is_object(value) ) { json_object_update(tmp, value); json_object_set(cursor, token, tmp); } else { ERR("JSON array or object expected at pos %zu\n", peek - buf); goto fail; } } else if(json_is_array(cursor)) { json_array_append(cursor, value); } else if(json_is_object(cursor) && json_is_object(value)) { json_object_update(cursor, value); } else { ERR("JSON array or object expected at pos %zu\n", peek - buf); goto fail; } } else if (token && strlen(token) != 0 ) { if (json_is_object(cursor)) { json_object_set(cursor, token, value); } else { ERR("JSON object expected at pos %zu\n", peek - buf); goto fail; } cursor = json_object_get(cursor, token); } else if (index_saved != -1 && json_is_array(parent)) { json_array_set(parent, index_saved, value); cursor = json_array_get(parent, index_saved); } else { ERR("invalid JSON path at pos %zu\n", peek - buf); goto fail; } json_decref(value); jsonp_free(buf); return 0; fail: json_decref(value); jsonp_free(buf); return -1; }