[tracker/wip/sam/resource: 8/15] libtracker-sparql: Add JSON-LD serialisation to TrackerResource
- From: Sam Thursfield <sthursfield src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tracker/wip/sam/resource: 8/15] libtracker-sparql: Add JSON-LD serialisation to TrackerResource
- Date: Mon, 18 Apr 2016 16:58:33 +0000 (UTC)
commit 9b1b3cc03bbce195e753c6e005c2ac8b47d24031
Author: Sam Thursfield <sam afuera me uk>
Date: Thu Apr 7 18:03:00 2016 +0100
libtracker-sparql: Add JSON-LD serialisation to TrackerResource
src/libtracker-sparql/tracker-resource.c | 143 ++++++++++++++++++++++++++++++
src/libtracker-sparql/tracker-resource.h | 2 +
2 files changed, 145 insertions(+), 0 deletions(-)
---
diff --git a/src/libtracker-sparql/tracker-resource.c b/src/libtracker-sparql/tracker-resource.c
index 191811f..289e15e 100644
--- a/src/libtracker-sparql/tracker-resource.c
+++ b/src/libtracker-sparql/tracker-resource.c
@@ -18,6 +18,7 @@
*/
#include <glib.h>
+#include <json-glib/json-glib.h>
#include <string.h>
@@ -561,6 +562,148 @@ tracker_resource_compare (TrackerResource *a,
};
+static void generate_jsonld_foreach (gpointer key, gpointer value_ptr, gpointer user_data);
+
+/* FIXME: this could hit an infinite loop if there are circular resource
+ * relationships, make sure those are tested & detected.
+ */
+/* This is not exposed publically right now because then everything including
+ * tracker-resource.h would need to pull in the json-glib dependency ...
+ */
+static JsonNode *
+tracker_resource_generate_jsonld (TrackerResource *self,
+ GError **error)
+{
+ /* FIXME: generate a JSON-LD context ! */
+
+ TrackerResourcePrivate *priv = GET_PRIVATE (self);
+ JsonBuilder *builder;
+ JsonNode *result;
+
+ builder = json_builder_new ();
+ json_builder_begin_object (builder);
+
+ /* The JSON-LD spec says it is "important that nodes have an identifier", but
+ * doesn't mandate one. I think it's better to omit the ID for blank nodes
+ * (where the caller passed NULL as an identifier) than to emit something
+ * SPARQL-specific like '_:123'.
+ */
+ if (strncmp (priv->identifier, "_:", 2) != 0) {
+ json_builder_set_member_name (builder, "@id");
+ json_builder_add_string_value (builder, priv->identifier);
+ }
+
+ g_hash_table_foreach (priv->properties, generate_jsonld_foreach, builder);
+
+ json_builder_end_object (builder);
+
+ result = json_builder_get_root (builder);
+ g_object_unref (builder);
+ return result;
+};
+
+static void
+append_value_to_json_builder (const GValue *value,
+ JsonBuilder *builder)
+{
+ JsonNode *node;
+
+ if (G_VALUE_HOLDS (value, TRACKER_TYPE_RESOURCE)) {
+ TrackerResource *resource;
+ GError *error = NULL;
+
+ resource = TRACKER_RESOURCE (g_value_get_object (value));
+ node = tracker_resource_generate_jsonld (resource, &error);
+
+ if (node) {
+ json_builder_add_value (builder, node);
+ } else {
+ g_warning ("Unable to serialize value: %s", error->message);
+ g_error_free (error);
+ }
+ } else if (G_VALUE_HOLDS (value, TRACKER_TYPE_URI)) {
+ /* URIs can be treated the same as strings in JSON-LD provided the @context
+ * sets the type of that property correctly. However, json_node_set_value()
+ * will reject a GValue holding TRACKER_TYPE_URI, so we have to extract the
+ * string manually here.
+ */
+ const char *uri = g_value_get_string (value);
+ node = json_node_new (JSON_NODE_VALUE);
+ json_node_set_string (node, uri);
+ json_builder_add_value (builder, node);
+ } else {
+ node = json_node_new (JSON_NODE_VALUE);
+ json_node_set_value (node, value);
+ json_builder_add_value (builder, node);
+ }
+}
+
+static void
+generate_jsonld_foreach (gpointer key,
+ gpointer value_ptr,
+ gpointer user_data)
+{
+ const char *property = key;
+ const GValue *value = value_ptr;
+ JsonBuilder *builder = JSON_BUILDER (user_data);
+
+ /* FIXME: shouldn't hardcode the unexpanded prefix here!!! */
+ if (strcmp (property, "rdf:type") == 0) {
+ property = "@type";
+ }
+
+ json_builder_set_member_name (builder, property);
+ if (G_VALUE_HOLDS (value, G_TYPE_PTR_ARRAY)) {
+ json_builder_begin_array (builder);
+ g_ptr_array_foreach (g_value_get_boxed (value), (GFunc) append_value_to_json_builder,
builder);
+ json_builder_end_array (builder);
+ } else {
+ append_value_to_json_builder (value, builder);
+ }
+}
+
+/**
+ * tracker_resource_print_jsonld:
+ * @resource: a #TrackerResource
+ * @error: address where an error can be returned
+ *
+ * Serialize all the information in @resource as a JSON-LD document.
+ *
+ * See <http://www.jsonld.org/> for more information on the JSON-LD
+ * serialization format.
+ *
+ * Returns: a newly-allocated string
+ *
+ * Since: 1.10
+ */
+char *
+tracker_resource_print_jsonld (TrackerResource *resource,
+ GError **error)
+{
+ GError *sub_error = NULL;
+ JsonNode *json_root_node;
+ JsonGenerator *generator;
+ char *result;
+
+ json_root_node = tracker_resource_generate_jsonld (resource, &sub_error);
+
+ if (json_root_node == NULL) {
+ g_propagate_error (error, sub_error);
+ return NULL;
+ }
+
+ generator = json_generator_new ();
+ json_generator_set_root (generator, json_root_node);
+ json_generator_set_pretty (generator, TRUE);
+
+ result = json_generator_to_data (generator, NULL);
+
+ json_node_free (json_root_node);
+ g_object_unref (generator);
+
+ return result;
+}
+
typedef struct {
TrackerNamespaceManager *namespaces;
GString *string;
diff --git a/src/libtracker-sparql/tracker-resource.h b/src/libtracker-sparql/tracker-resource.h
index fe67b57..f225a64 100644
--- a/src/libtracker-sparql/tracker-resource.h
+++ b/src/libtracker-sparql/tracker-resource.h
@@ -75,6 +75,8 @@ gint tracker_resource_identifier_compare_func (TrackerResource *resource, const
char *tracker_resource_print_turtle(TrackerResource *self, TrackerNamespaceManager *namespaces);
+char *tracker_resource_print_jsonld (TrackerResource *self, GError **error);
+
void tracker_resource_generate_sparql_update (TrackerResource *self, TrackerSparqlBuilder *builder,
TrackerNamespaceManager *namespaces, const char *graph_id, GError **error);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]