summaryrefslogtreecommitdiff
path: root/json-glib/tests
diff options
context:
space:
mode:
authorEmmanuele Bassi <ebassi@gnome.org>2011-05-28 14:36:43 +0100
committerEmmanuele Bassi <ebassi@linux.intel.com>2011-05-31 23:02:35 +0100
commit4ea8cd43986d5888fb8e809a198d6b0331b12480 (patch)
treef3253bf151093e26285c082ddabf72a079efc857 /json-glib/tests
parent8b778252358ddb28936c6c9192a84f76368ca122 (diff)
downloadjson-glib-4ea8cd43986d5888fb8e809a198d6b0331b12480.tar.gz
Add initial JSONPath implementation
JSONPath is a JSON query syntax similar to what XPath does for XML; using JSONPath it's possible to address a specific node (or set of nodes) inside a JSON document. The JsonPath class is a simple implementation of part of the JSONPath proposal, as formalised by Stefan Gössner here: http://goessner.net/articles/JsonPath/ The covered operators are: • root, or '$'; • child, both using the dot-notation and the bracket notation; • recursive descent, or '..'; • subscript, or '[]'; • set, or '[,]'; • slice, or '[start:end:step]'. The only missing operators are the filter, or '?()' and the script, or '()', because implementing a JavaScript interpreter inside JSON-GLib is not one of my greatest aspirations. It should be possible, though, to parse and evaluate simple arithmetic conditions, in the future. The JsonPath methods are pretty straightforward: a JsonPath instance should be created and used to compile an expression; the compilation might result in a syntax error or not. Then, the JsonPath instance can be used to match any JSON tree. Like the other JSONPath implementations, JsonPath returns a JSON array of matching nodes. A simple, one-off static method called json_path_query() is also provided; the method wraps the JsonPath creation, the expression compilation, and the matching, as well as disposing the JsonPath instance once done. For the time being, only positive testing is provided; negative testing for the expression compilation will follow.
Diffstat (limited to 'json-glib/tests')
-rw-r--r--json-glib/tests/Makefile.am1
-rw-r--r--json-glib/tests/path-test.c143
2 files changed, 144 insertions, 0 deletions
diff --git a/json-glib/tests/Makefile.am b/json-glib/tests/Makefile.am
index fea656d..5e21412 100644
--- a/json-glib/tests/Makefile.am
+++ b/json-glib/tests/Makefile.am
@@ -26,6 +26,7 @@ TEST_PROGS += \
builder-test \
reader-test \
gvariant-test \
+ path-test \
boxed \
serialize-simple \
serialize-complex \
diff --git a/json-glib/tests/path-test.c b/json-glib/tests/path-test.c
new file mode 100644
index 0000000..3a5e41c
--- /dev/null
+++ b/json-glib/tests/path-test.c
@@ -0,0 +1,143 @@
+#include <string.h>
+#include <glib.h>
+#include <json-glib/json-glib.h>
+
+static const char *test_json =
+"{ \"store\": {"
+" \"book\": [ "
+" { \"category\": \"reference\","
+" \"author\": \"Nigel Rees\","
+" \"title\": \"Sayings of the Century\","
+" \"price\": \"8.95\""
+" },"
+" { \"category\": \"fiction\","
+" \"author\": \"Evelyn Waugh\","
+" \"title\": \"Sword of Honour\","
+" \"price\": \"12.99\""
+" },"
+" { \"category\": \"fiction\","
+" \"author\": \"Herman Melville\","
+" \"title\": \"Moby Dick\","
+" \"isbn\": \"0-553-21311-3\","
+" \"price\": \"8.99\""
+" },"
+" { \"category\": \"fiction\","
+" \"author\": \"J. R. R. Tolkien\","
+" \"title\": \"The Lord of the Rings\","
+" \"isbn\": \"0-395-19395-8\","
+" \"price\": \"22.99\""
+" }"
+" ],"
+" \"bicycle\": {"
+" \"color\": \"red\","
+" \"price\": \"19.95\""
+" }"
+" }"
+"}";
+
+static const char *test_expressions[] = {
+ "$.store.book[0].title",
+ "$['store']['book'][0]['title']",
+ "$.store.book[*].author",
+ "$..author",
+ "$.store.*",
+ "$.store..price",
+ "$..book[2]",
+ "$..book[-1:]",
+ "$..book[0,1]",
+ "$..book[:2]",
+};
+
+static const char *test_results[] = {
+ "[\"Sayings of the Century\"]",
+ "[\"Sayings of the Century\"]",
+ "[\"Nigel Rees\",\"Evelyn Waugh\",\"Herman Melville\",\"J. R. R. Tolkien\"]",
+ "[\"Nigel Rees\",\"Evelyn Waugh\",\"Herman Melville\",\"J. R. R. Tolkien\"]",
+ NULL,
+ "[\"8.95\",\"12.99\",\"8.99\",\"22.99\",\"19.95\"]",
+ "[{\"category\":\"fiction\",\"author\":\"Herman Melville\",\"title\":\"Moby Dick\",\"isbn\":\"0-553-21311-3\",\"price\":\"8.99\"}]",
+ "[{\"category\":\"fiction\",\"author\":\"J. R. R. Tolkien\",\"title\":\"The Lord of the Rings\",\"isbn\":\"0-395-19395-8\",\"price\":\"22.99\"}]",
+ "[{\"category\":\"reference\",\"author\":\"Nigel Rees\",\"title\":\"Sayings of the Century\",\"price\":\"8.95\"},{\"category\":\"fiction\",\"author\":\"Evelyn Waugh\",\"title\":\"Sword of Honour\",\"price\":\"12.99\"}]",
+ "[{\"category\":\"reference\",\"author\":\"Nigel Rees\",\"title\":\"Sayings of the Century\",\"price\":\"8.95\"},{\"category\":\"fiction\",\"author\":\"Evelyn Waugh\",\"title\":\"Sword of Honour\",\"price\":\"12.99\"}]",
+};
+
+static void
+test_expression (void)
+{
+ JsonPath *path = json_path_new ();
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (test_expressions); i++)
+ {
+ const char *expr = test_expressions[i];
+ GError *error = NULL;
+
+ g_assert (json_path_compile (path, expr, &error));
+ g_assert_no_error (error);
+ }
+
+ g_object_unref (path);
+}
+
+static void
+test_match (void)
+{
+ JsonParser *parser = json_parser_new ();
+ JsonGenerator *gen = json_generator_new ();
+ JsonPath *path = json_path_new ();
+ JsonNode *root;
+ int i;
+
+ json_parser_load_from_data (parser, test_json, -1, NULL);
+ root = json_parser_get_root (parser);
+
+ for (i = 0; i < G_N_ELEMENTS (test_expressions); i++)
+ {
+ const char *expr = test_expressions[i];
+ const char *res = test_results[i];
+ JsonNode *matches;
+ char *str;
+
+ if (res == NULL || *res == '\0')
+ continue;
+
+ g_assert (json_path_compile (path, expr, NULL));
+
+ matches = json_path_match (path, root);
+ g_assert (JSON_NODE_HOLDS_ARRAY (matches));
+
+ json_generator_set_root (gen, matches);
+ str = json_generator_to_data (gen, NULL);
+
+ if (g_test_verbose ())
+ {
+ g_print ("* expr[%02d]: '%s' =>\n"
+ "- result: %s\n"
+ "- expected: %s\n",
+ i, expr, str, res);
+ }
+
+ g_assert_cmpstr (str, ==, res);
+
+ g_free (str);
+ json_node_free (matches);
+ }
+
+ g_object_unref (parser);
+ g_object_unref (path);
+ g_object_unref (gen);
+}
+
+int
+main (int argc,
+ char *argv[])
+{
+ g_type_init ();
+ g_test_init (&argc, &argv, NULL);
+ g_test_bug_base ("http://bugzilla.gnome.org/show_bug.cgi?id=");
+
+ g_test_add_func ("/path/expressions", test_expression);
+ g_test_add_func ("/path/match", test_match);
+
+ return g_test_run ();
+}