Commit 5b816ff8 authored by Emmanuele Bassi's avatar Emmanuele Bassi

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`.
parent ce0f83a4
Pipeline #900 passed with stage
in 2 minutes and 22 seconds
......@@ -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
......
......@@ -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:
......@@ -707,39 +797,6 @@ json_object_get_null_member (JsonObject *object,
return 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
*/
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
......
......@@ -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);
......
......@@ -70,6 +70,25 @@ test_set_member (void)
json_object_unref (object);
}
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)
{
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment