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;
}
Exemple #2
0
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;
}
Exemple #3
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;
}