mirror of
https://github.com/kgabis/parson.git
synced 2025-11-14 20:17:39 +00:00
Add query support
This commit is contained in:
parent
642f0cb4f5
commit
477c23e557
44
README.md
44
README.md
@ -75,6 +75,50 @@ Date SHA Author
|
||||
...
|
||||
```
|
||||
|
||||
###Query
|
||||
When you simply read JSON and get values without modifying it, you can use '.' and '[]' to traverse object and array hierarchy.
|
||||
```c
|
||||
void query_example(void) {
|
||||
JSON_Value *root_value;
|
||||
char *json_string;
|
||||
|
||||
/* json string to parse */
|
||||
json_string = "{"
|
||||
"\"list\":["
|
||||
"{"
|
||||
"\"index\":0,"
|
||||
"\"data\":{"
|
||||
"\"prop\":\"value\""
|
||||
"}"
|
||||
"},"
|
||||
"{"
|
||||
"\"index\":1,"
|
||||
"\"data\":{"
|
||||
"\"prop\":null"
|
||||
"}"
|
||||
"},"
|
||||
"{"
|
||||
"\"index\":2,"
|
||||
"\"data\":{"
|
||||
"\"prop\":123"
|
||||
"}"
|
||||
"}"
|
||||
"]"
|
||||
"}";
|
||||
|
||||
/* parsing json string */
|
||||
root_value = json_parse_string(json_string);
|
||||
|
||||
if (JSONObject == json_type(root_value)) {
|
||||
printf("Query: \"%s\", Result: \"%s\"\n", ".list[0].data.prop", json_value_query_string(root_value, ".list[0].data.prop"));
|
||||
printf("Query: \"%s\", Result: \"%d\"\n", ".list[2].data.prop", (int)json_value_query_number(root_value, ".list[2].data.prop"));
|
||||
}
|
||||
|
||||
/* cleanup code */
|
||||
json_value_free(root_value);
|
||||
}
|
||||
```
|
||||
|
||||
###Persistence
|
||||
In this example I'm using parson to save user information to a file and then load it and validate later.
|
||||
```c
|
||||
|
||||
116
parson.c
116
parson.c
@ -1929,3 +1929,119 @@ void json_set_allocation_functions(JSON_Malloc_Function malloc_fun, JSON_Free_Fu
|
||||
parson_malloc = malloc_fun;
|
||||
parson_free = free_fun;
|
||||
}
|
||||
|
||||
JSON_Value * json_value_query_value(JSON_Value *value, const char *query) {
|
||||
const char *query_start = query, *field_start = query, *field_end = NULL;
|
||||
char *name = NULL;
|
||||
JSON_Value *return_value = NULL;
|
||||
int in_bracket = 0, is_digit = 1;
|
||||
while (query != NULL && *query != '\0') {
|
||||
switch (*query) {
|
||||
case '[':
|
||||
if (in_bracket) {
|
||||
// Ignore
|
||||
} else if (field_start == query) {
|
||||
field_start = query + 1;
|
||||
in_bracket = 1;
|
||||
} else if (field_start < query) {
|
||||
field_end = query;
|
||||
}
|
||||
break;
|
||||
case ']':
|
||||
if (in_bracket) {
|
||||
field_end = query;
|
||||
query++;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
case '.':
|
||||
if (in_bracket) {
|
||||
// Ignore
|
||||
} else if (field_start == query) {
|
||||
if (query_start == query) {
|
||||
field_start = query + 1;
|
||||
} else {
|
||||
// Query ".."
|
||||
field_end = query;
|
||||
}
|
||||
} else if (field_start < query) {
|
||||
field_end = query;
|
||||
query++;
|
||||
}
|
||||
break;
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
// Keep is_digit = 1
|
||||
break;
|
||||
default :
|
||||
is_digit = 0;
|
||||
break;
|
||||
}
|
||||
if (field_end != NULL) {
|
||||
break;
|
||||
} else {
|
||||
query++;
|
||||
}
|
||||
}
|
||||
if (query != NULL && query_start < query && !in_bracket && field_end == NULL) {
|
||||
field_end = query;
|
||||
}
|
||||
if (field_end == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
name = parson_strndup(field_start, field_end - field_start);
|
||||
if (name == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (0 < strlen(name)) {
|
||||
switch (json_type(value)) {
|
||||
case JSONObject:
|
||||
if (is_digit) {
|
||||
return_value = json_object_get_value_at(json_value_get_object(value), atol(name));
|
||||
} else {
|
||||
return_value = json_object_get_value(json_value_get_object(value), name);
|
||||
}
|
||||
break;
|
||||
case JSONArray:
|
||||
if (!is_digit) {
|
||||
return NULL;
|
||||
}
|
||||
return_value = json_array_get_value(json_value_get_array(value), atol(name));
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
return_value = value;
|
||||
}
|
||||
parson_free(name);
|
||||
if (*query != '\0' && return_value != NULL) {
|
||||
return_value = json_value_query_value(return_value, query);
|
||||
}
|
||||
return return_value;
|
||||
}
|
||||
|
||||
const char * json_value_query_string(JSON_Value *value, const char *query) {
|
||||
return json_value_get_string(json_value_query_value(value, query));
|
||||
}
|
||||
|
||||
JSON_Object * json_value_query_object(JSON_Value *value, const char *query) {
|
||||
return json_value_get_object(json_value_query_value(value, query));
|
||||
}
|
||||
|
||||
JSON_Array * json_value_query_array(JSON_Value *value, const char *query) {
|
||||
return json_value_get_array(json_value_query_value(value, query));
|
||||
}
|
||||
|
||||
double json_value_query_number(JSON_Value *value, const char *query) {
|
||||
return json_value_get_number(json_value_query_value(value, query));
|
||||
}
|
||||
|
||||
int json_value_query_boolean(JSON_Value *value, const char *query) {
|
||||
return json_value_get_boolean(json_value_query_value(value, query));
|
||||
}
|
||||
|
||||
JSON_Value * json_query(JSON_Value *value, const char *query) {
|
||||
return json_value_query_value(value, query);
|
||||
}
|
||||
|
||||
9
parson.h
9
parson.h
@ -224,6 +224,15 @@ const char * json_string (const JSON_Value *value);
|
||||
double json_number (const JSON_Value *value);
|
||||
int json_boolean(const JSON_Value *value);
|
||||
|
||||
/* Query */
|
||||
JSON_Value * json_value_query_value (JSON_Value *value, const char *query);
|
||||
const char * json_value_query_string (JSON_Value *value, const char *query);
|
||||
JSON_Object * json_value_query_object (JSON_Value *value, const char *query);
|
||||
JSON_Array * json_value_query_array (JSON_Value *value, const char *query);
|
||||
double json_value_query_number (JSON_Value *value, const char *query); /* returns 0 on fail */
|
||||
int json_value_query_boolean(JSON_Value *value, const char *query); /* returns -1 on fail */
|
||||
JSON_Value * json_query (JSON_Value *value, const char *query); /* shorter version of json_value_query_value */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
30
tests.c
30
tests.c
@ -208,6 +208,36 @@ void test_suite_2(JSON_Value *root_value) {
|
||||
TEST(json_object_get_object(root_object, "empty object") != NULL);
|
||||
TEST(json_object_get_array(root_object, "empty array") != NULL);
|
||||
|
||||
TEST((json_value_query_value(root_value, ".") == root_value));
|
||||
TEST((json_value_query_value(root_value, "..") == root_value));
|
||||
TEST((json_value_query_value(root_value, "...") == root_value));
|
||||
TEST((json_value_query_value(root_value, "[]") == root_value));
|
||||
TEST((json_value_query_value(root_value, NULL) == NULL));
|
||||
TEST((json_value_query_value(root_value, "") == NULL));
|
||||
TEST((json_value_query_value(root_value, "noexist") == NULL));
|
||||
TEST((json_value_query_value(root_value, ".noexist") == NULL));
|
||||
TEST((json_value_query_value(root_value, "..noexist") == NULL));
|
||||
TEST((json_value_query_value(root_value, "noexist.prop") == NULL));
|
||||
TEST((json_value_query_value(root_value, ".noexist.prop") == NULL));
|
||||
TEST((json_value_query_value(root_value, "..noexist.prop") == NULL));
|
||||
TEST((json_value_query_value(root_value, ".[.no[[exist].prop") == NULL));
|
||||
TEST((json_value_query_value(root_value, ".object].nested true") == NULL));
|
||||
TEST(STREQ(json_value_query_string(root_value, "[0]"), "lorem ipsum"));
|
||||
TEST(STREQ(json_value_query_string(root_value, "object.nested object.lorem"), "ipsum"));
|
||||
TEST(STREQ(json_value_query_string(root_value, "object.nested object[0]"), "ipsum"));
|
||||
TEST(STREQ(json_value_query_string(root_value, "object.nested array[0]"), "lorem"));
|
||||
TEST(STREQ(json_value_query_string(root_value, ".object[nested array][1]"), "ipsum"));
|
||||
TEST((json_value_query_number(root_value, ".object[nested number]") == 123));
|
||||
TEST((json_value_query_boolean(root_value, ".object[nested true]") == 1));
|
||||
|
||||
array = json_value_query_array(root_value, ".object[nested array][]");
|
||||
TEST(array != NULL);
|
||||
TEST(json_array_get_count(array) == 2);
|
||||
|
||||
array = json_value_query_array(root_value, ".[x^2 array][]");
|
||||
TEST(array != NULL);
|
||||
TEST(json_array_get_count(array) == 11);
|
||||
|
||||
}
|
||||
|
||||
void test_suite_2_no_comments(void) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user