[json-glib/get-with-default: 2/2] Add with_default() variant for JsonObject getters
- From: Emmanuele Bassi <ebassi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [json-glib/get-with-default: 2/2] Add with_default() variant for JsonObject getters
- Date: Tue, 14 Nov 2017 19:55:12 +0000 (UTC)
commit 5b816ff8df9e563c1e9c3ae05ee97d46924f9b40
Author: Emmanuele Bassi <ebassi gnome org>
Date: Tue Nov 14 17:16:40 2017 +0000
Add with_default() variant for JsonObject getters
When using the typed getters for JsonObject, the existing API will
automatically fail if the member requested is not present. This is
generally good practice, because JSON data typically does not have a
schema, and thus is has to be validated "on the go"; a JSON object
member that contains `null`, or `0`, or `false`, is indistinguishable
from a JSON object member that does not exist, so we cannot simply
return a scalar value and be done with it.
We can provide an escape hatch, though, for the crowd writing parsers
for JSON data; by using Python as the model, we can add methods that
take a default value as a parameter, and return it as a fallback value
if the requested object member does not exist, or if it's set to `null`.
doc/json-glib-sections.txt | 12 ++-
json-glib/json-object.c | 205 +++++++++++++++++++++++++++++----------------
json-glib/json-types.h | 38 ++++++---
json-glib/tests/object.c | 20 +++++
4 files changed, 186 insertions(+), 89 deletions(-)
---
diff --git a/doc/json-glib-sections.txt b/doc/json-glib-sections.txt
index 44942c4..ada0895 100644
--- a/doc/json-glib-sections.txt
+++ b/doc/json-glib-sections.txt
@@ -31,18 +31,22 @@ json_object_iter_next
<SUBSECTION>
json_object_set_array_member
json_object_get_array_member
+json_object_set_object_member
+json_object_get_object_member
+json_object_set_null_member
+json_object_get_null_member
json_object_set_boolean_member
json_object_get_boolean_member
+json_object_get_boolean_member_with_default
json_object_set_double_member
json_object_get_double_member
+json_object_get_double_member_with_default
json_object_set_int_member
json_object_get_int_member
-json_object_set_null_member
-json_object_get_null_member
-json_object_set_object_member
-json_object_get_object_member
+json_object_get_int_member_with_default
json_object_set_string_member
json_object_get_string_member
+json_object_get_string_member_with_default
<SUBSECTION Private>
JSON_TYPE_OBJECT
diff --git a/json-glib/json-object.c b/json-glib/json-object.c
index 29b9401..bb33ec0 100644
--- a/json-glib/json-object.c
+++ b/json-glib/json-object.c
@@ -579,10 +579,50 @@ json_object_get_member (JsonObject *object,
return object_get_member_internal (object, member_name);
}
+#define JSON_OBJECT_GET(ret_type,type_name) \
+ret_type \
+json_object_get_ ##type_name## _member (JsonObject *object, \
+ const char *member_name) \
+{ \
+ g_return_val_if_fail (object != NULL, (ret_type) 0); \
+ g_return_val_if_fail (member_name != NULL, (ret_type) 0); \
+\
+ JsonNode *node = object_get_member_internal (object, member_name); \
+ g_return_val_if_fail (node != NULL, (ret_type) 0); \
+\
+ if (JSON_NODE_HOLDS_NULL (node)) \
+ return (ret_type) 0; \
+\
+ g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, (ret_type) 0); \
+\
+ return json_node_get_ ##type_name (node); \
+}
+
+#define JSON_OBJECT_GET_DEFAULT(ret_type,type_name) \
+ret_type \
+json_object_get_ ##type_name## _member_with_default (JsonObject *object, \
+ const char *member_name, \
+ ret_type default_value) \
+{ \
+ g_return_val_if_fail (object != NULL, default_value); \
+ g_return_val_if_fail (member_name != NULL, default_value); \
+\
+ JsonNode *node = object_get_member_internal (object, member_name); \
+ if (node == NULL) \
+ return default_value; \
+\
+ if (JSON_NODE_HOLDS_NULL (node)) \
+ return default_value; \
+\
+ g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, default_value); \
+\
+ return json_node_get_ ##type_name (node); \
+}
+
/**
* json_object_get_int_member:
* @object: a #JsonObject
- * @member_name: the name of the member
+ * @member_name: the name of the @object member
*
* Convenience function that retrieves the integer value
* stored in @member_name of @object
@@ -593,21 +633,26 @@ json_object_get_member (JsonObject *object,
*
* Since: 0.8
*/
-gint64
-json_object_get_int_member (JsonObject *object,
- const gchar *member_name)
-{
- JsonNode *node;
-
- g_return_val_if_fail (object != NULL, 0);
- g_return_val_if_fail (member_name != NULL, 0);
+JSON_OBJECT_GET (gint64, int)
- node = object_get_member_internal (object, member_name);
- g_return_val_if_fail (node != NULL, 0);
- g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, 0);
-
- return json_node_get_int (node);
-}
+/**
+ * json_object_get_int_member_with_default:
+ * @object: a #JsonObject
+ * @member_name: the name of the @object member
+ * @default_value: the value to return if @member_name is not valid
+ *
+ * Convenience function that retrieves the integer value
+ * stored in @member_name of @object.
+ *
+ * If @member_name does not exist, does not contain a scalar value,
+ * or contains `null`, then @default_value is returned instead.
+ *
+ * Returns: the integer value of the object's member, or the
+ * given default
+ *
+ * Since: 1.6
+ */
+JSON_OBJECT_GET_DEFAULT (gint64, int)
/**
* json_object_get_double_member:
@@ -623,21 +668,26 @@ json_object_get_int_member (JsonObject *object,
*
* Since: 0.8
*/
-gdouble
-json_object_get_double_member (JsonObject *object,
- const gchar *member_name)
-{
- JsonNode *node;
-
- g_return_val_if_fail (object != NULL, 0.0);
- g_return_val_if_fail (member_name != NULL, 0.0);
-
- node = object_get_member_internal (object, member_name);
- g_return_val_if_fail (node != NULL, 0.0);
- g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, 0.0);
+JSON_OBJECT_GET (gdouble, double)
- return json_node_get_double (node);
-}
+/**
+ * json_object_get_double_member_with_default:
+ * @object: a #JsonObject
+ * @member_name: the name of the @object member
+ * @default_value: the value to return if @member_name is not valid
+ *
+ * Convenience function that retrieves the floating point value
+ * stored in @member_name of @object.
+ *
+ * If @member_name does not exist, does not contain a scalar value,
+ * or contains `null`, then @default_value is returned instead.
+ *
+ * Returns: the floating point value of the object's member, or the
+ * given default
+ *
+ * Since: 1.6
+ */
+JSON_OBJECT_GET_DEFAULT (double, double)
/**
* json_object_get_boolean_member:
@@ -653,21 +703,61 @@ json_object_get_double_member (JsonObject *object,
*
* Since: 0.8
*/
-gboolean
-json_object_get_boolean_member (JsonObject *object,
- const gchar *member_name)
-{
- JsonNode *node;
+JSON_OBJECT_GET (gboolean, boolean)
- g_return_val_if_fail (object != NULL, FALSE);
- g_return_val_if_fail (member_name != NULL, FALSE);
+/**
+ * json_object_get_boolean_member_with_default:
+ * @object: a #JsonObject
+ * @member_name: the name of the @object member
+ * @default_value: the value to return if @member_name is not valid
+ *
+ * Convenience function that retrieves the boolean value
+ * stored in @member_name of @object.
+ *
+ * If @member_name does not exist, does not contain a scalar value,
+ * or contains `null`, then @default_value is returned instead.
+ *
+ * Returns: the boolean value of the object's member, or the
+ * given default
+ *
+ * Since: 1.6
+ */
+JSON_OBJECT_GET_DEFAULT (gboolean, boolean)
- node = object_get_member_internal (object, member_name);
- g_return_val_if_fail (node != NULL, FALSE);
- g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_VALUE, FALSE);
+/**
+ * json_object_get_string_member:
+ * @object: a #JsonObject
+ * @member_name: the name of the member
+ *
+ * Convenience function that retrieves the string value
+ * stored in @member_name of @object
+ *
+ * See also: json_object_get_member()
+ *
+ * Return value: the string value of the object's member
+ *
+ * Since: 0.8
+ */
+JSON_OBJECT_GET (const gchar *, string)
- return json_node_get_boolean (node);
-}
+/**
+ * json_object_get_string_member_with_default:
+ * @object: a #JsonObject
+ * @member_name: the name of the @object member
+ * @default_value: the value to return if @member_name is not valid
+ *
+ * Convenience function that retrieves the string value
+ * stored in @member_name of @object.
+ *
+ * If @member_name does not exist, does not contain a scalar value,
+ * or contains `null`, then @default_value is returned instead.
+ *
+ * Returns: the string value of the object's member, or the
+ * given default
+ *
+ * Since: 1.6
+ */
+JSON_OBJECT_GET_DEFAULT (const char *, string)
/**
* json_object_get_null_member:
@@ -708,39 +798,6 @@ json_object_get_null_member (JsonObject *object,
}
/**
- * json_object_get_string_member:
- * @object: a #JsonObject
- * @member_name: the name of the member
- *
- * Convenience function that retrieves the string value
- * stored in @member_name of @object
- *
- * See also: json_object_get_member()
- *
- * Return value: the string value of the object's member
- *
- * Since: 0.8
- */
-const gchar *
-json_object_get_string_member (JsonObject *object,
- const gchar *member_name)
-{
- JsonNode *node;
-
- g_return_val_if_fail (object != NULL, NULL);
- g_return_val_if_fail (member_name != NULL, NULL);
-
- node = object_get_member_internal (object, member_name);
- g_return_val_if_fail (node != NULL, NULL);
- g_return_val_if_fail (JSON_NODE_HOLDS_VALUE (node) || JSON_NODE_HOLDS_NULL (node), NULL);
-
- if (JSON_NODE_HOLDS_NULL (node))
- return NULL;
-
- return json_node_get_string (node);
-}
-
-/**
* json_object_get_array_member:
* @object: a #JsonObject
* @member_name: the name of the member
diff --git a/json-glib/json-types.h b/json-glib/json-types.h
index d845f94..220b706 100644
--- a/json-glib/json-types.h
+++ b/json-glib/json-types.h
@@ -358,17 +358,33 @@ JSON_AVAILABLE_IN_1_0
JsonNode * json_object_dup_member (JsonObject *object,
const gchar *member_name);
JSON_AVAILABLE_IN_1_0
-gint64 json_object_get_int_member (JsonObject *object,
- const gchar *member_name);
-JSON_AVAILABLE_IN_1_0
-gdouble json_object_get_double_member (JsonObject *object,
- const gchar *member_name);
-JSON_AVAILABLE_IN_1_0
-gboolean json_object_get_boolean_member (JsonObject *object,
- const gchar *member_name);
-JSON_AVAILABLE_IN_1_0
-const gchar * json_object_get_string_member (JsonObject *object,
- const gchar *member_name);
+gint64 json_object_get_int_member (JsonObject *object,
+ const gchar *member_name);
+JSON_AVAILABLE_IN_1_6
+gint64 json_object_get_int_member_with_default (JsonObject *object,
+ const char *member_name,
+ gint64 default_value);
+JSON_AVAILABLE_IN_1_0
+gdouble json_object_get_double_member (JsonObject *object,
+ const gchar *member_name);
+JSON_AVAILABLE_IN_1_6
+double json_object_get_double_member_with_default (JsonObject *object,
+ const char *member_name,
+ double default_value);
+JSON_AVAILABLE_IN_1_0
+gboolean json_object_get_boolean_member (JsonObject *object,
+ const gchar *member_name);
+JSON_AVAILABLE_IN_1_6
+gboolean json_object_get_boolean_member_with_default (JsonObject *object,
+ const char *member_name,
+ gboolean default_value);
+JSON_AVAILABLE_IN_1_0
+const gchar * json_object_get_string_member (JsonObject *object,
+ const gchar *member_name);
+JSON_AVAILABLE_IN_1_6
+const char * json_object_get_string_member_with_default (JsonObject *object,
+ const char *member_name,
+ const char *default_value);
JSON_AVAILABLE_IN_1_0
gboolean json_object_get_null_member (JsonObject *object,
const gchar *member_name);
diff --git a/json-glib/tests/object.c b/json-glib/tests/object.c
index 03a478c..772265a 100644
--- a/json-glib/tests/object.c
+++ b/json-glib/tests/object.c
@@ -71,6 +71,25 @@ test_set_member (void)
}
static void
+test_get_member_default (void)
+{
+ JsonObject *object = json_object_new ();
+
+ json_object_set_int_member (object, "foo", 42);
+ json_object_set_boolean_member (object, "bar", TRUE);
+ json_object_set_string_member (object, "hello", "world");
+
+ g_assert_cmpint (json_object_get_int_member_with_default (object, "foo", 47), ==, 42);
+ g_assert_true (json_object_get_boolean_member_with_default (object, "bar", FALSE));
+ g_assert_cmpstr (json_object_get_string_member_with_default (object, "hello", "wisconsin"), ==, "world");
+
+ g_assert_cmpint (json_object_get_int_member_with_default (object, "no", 4), ==, 4);
+ g_assert_cmpstr (json_object_get_string_member_with_default (object, "doesNotExist", "indeed"), ==,
"indeed");
+
+ json_object_unref (object);
+}
+
+static void
test_remove_member (void)
{
JsonObject *object = json_object_new ();
@@ -204,6 +223,7 @@ main (int argc,
g_test_add_func ("/object/empty-object", test_empty_object);
g_test_add_func ("/object/add-member", test_add_member);
g_test_add_func ("/object/set-member", test_set_member);
+ g_test_add_func ("/object/get-member-default", test_get_member_default);
g_test_add_func ("/object/remove-member", test_remove_member);
g_test_add_func ("/object/foreach-member", test_foreach_member);
g_test_add_func ("/object/iter", test_iter);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]