static gboolean parse_json (GDataParsable *parsable, JsonReader *reader, gpointer user_data, GError **error) { gboolean success; if (g_strcmp0 (json_reader_get_member_name (reader), "role") == 0) { gchar *role = NULL; /* owned */ g_assert (gdata_parser_string_from_json_member (reader, "role", P_REQUIRED | P_NON_EMPTY, &role, &success, error)); if (!success) { return FALSE; } gdata_access_rule_set_role (GDATA_ACCESS_RULE (parsable), role_v3_to_v2 (role)); g_free (role); return TRUE; } else if (g_strcmp0 (json_reader_get_member_name (reader), "scope") == 0) { const gchar *scope_type; const gchar *scope_value; /* Check this is an object. */ if (!json_reader_is_object (reader)) { return gdata_parser_error_required_json_content_missing (reader, error); } json_reader_read_member (reader, "type"); scope_type = json_reader_get_string_value (reader); json_reader_end_member (reader); json_reader_read_member (reader, "value"); scope_value = json_reader_get_string_value (reader); json_reader_end_member (reader); /* Scope type is required. */ if (scope_type == NULL) { return gdata_parser_error_required_json_content_missing (reader, error); } gdata_access_rule_set_scope (GDATA_ACCESS_RULE (parsable), scope_type_v3_to_v2 (scope_type), scope_value); return TRUE; } return GDATA_PARSABLE_CLASS (gdata_calendar_access_rule_parent_class)->parse_json (parsable, reader, user_data, error); }
static gboolean parse_json (GDataParsable *parsable, JsonReader *reader, gpointer user_data, GError **error) { GDataFreebaseTopicResultPrivate *priv = GDATA_FREEBASE_TOPIC_RESULT (parsable)->priv; const gchar *member_name; GDATA_PARSABLE_CLASS (gdata_freebase_topic_result_parent_class)->parse_json (parsable, reader, user_data, error); member_name = json_reader_get_member_name (reader); if (member_name == NULL) return FALSE; if (strcmp (member_name, "id") == 0) { /* We only expect one member containing information */ g_assert (priv->object == NULL); priv->object = object_new (json_reader_get_string_value (reader)); } else if (strcmp (member_name, "property") == 0) { reader_get_properties (reader, priv->object, error); } else { return FALSE; } return TRUE; }
/* * gdata_parser_boolean_from_json_member: * @reader: #JsonReader cursor object to read the JSON node from * @member_name: the name of the JSON object member to parse * @options: a bitwise combination of parsing options from #GDataParserOptions, or %P_NONE * @output: (out caller-allocates): the return location for the parsed boolean value * @success: (out caller-allocates): the return location for a value which is %TRUE if the boolean was parsed successfully, %FALSE if an error was encountered, * and undefined if @member_name was not found in the current object in @reader * @error: (allow-none): a #GError, or %NULL * * Gets the boolean value of the @member_name member of the current object in the #JsonReader, subject to various checks specified by @options. * * If no member matching @member_name can be found in the current @reader JSON object, %FALSE will be returned, @error will be unset and @success will be unset. @output will be undefined. * * If @member_name is found but one of the checks specified by @options fails, %TRUE will be returned, @error will be set to a * %GDATA_SERVICE_ERROR_PROTOCOL_ERROR error and @success will be set to %FALSE. @output will be undefined. * * If @member_name is found and all of the checks specified by @options pass, %TRUE will be returned, @error will be unset and * @success will be set to %TRUE. @output will be set to the parsed value. * * The reason for returning the success of the parsing in @success is so that calls to gdata_parser_boolean_from_json_node() can be chained * together in a large "or" statement based on their return values, for the purposes of determining whether any of the calls matched * a given JSON node. If any of the calls to gdata_parser_boolean_from_json_node() return %TRUE, the value of @success can be examined. * * Return value: %TRUE if @member_name was found, %FALSE otherwise * * Since: 0.15.0 */ gboolean gdata_parser_boolean_from_json_member (JsonReader *reader, const gchar *member_name, GDataParserOptions options, gboolean *output, gboolean *success, GError **error) { gboolean val; const GError *child_error = NULL; /* Check if there's such an element. */ if (g_strcmp0 (json_reader_get_member_name (reader), member_name) != 0) { return FALSE; } /* Get the boolean. Check for parse errors. */ val = json_reader_get_boolean_value (reader); child_error = json_reader_get_error (reader); if (child_error != NULL) { *success = parser_error_from_json_error (reader, child_error, error); return TRUE; } /* Success! */ *output = val; *success = TRUE; return TRUE; }
/* * gdata_parser_string_from_json_member: * @reader: #JsonReader cursor object to read JSON node from * @member_name: the name of the member to parse * @options: a bitwise combination of parsing options from #GDataParserOptions, or %P_NONE * @output: the return location for the parsed string content * @success: the return location for a value which is %TRUE if the string was parsed successfully, %FALSE if an error was encountered, * and undefined if @element didn't match @element_name * @error: a #GError, or %NULL * * Gets the string content of @element if its name is @element_name, subject to various checks specified by @options. * * If @element doesn't match @element_name, %FALSE will be returned, @error will be unset and @success will be unset. * * If @element matches @element_name but one of the checks specified by @options fails, %TRUE will be returned, @error will be set to a * %GDATA_SERVICE_ERROR_PROTOCOL_ERROR error and @success will be set to %FALSE. * * If @element matches @element_name and all of the checks specified by @options pass, %TRUE will be returned, @error will be unset and * @success will be set to %TRUE. * * The reason for returning the success of the parsing in @success is so that calls to gdata_parser_string_from_element() can be chained * together in a large "or" statement based on their return values, for the purposes of determining whether any of the calls matched * a given @element. If any of the calls to gdata_parser_string_from_element() return %TRUE, the value of @success can be examined. * * Return value: %TRUE if @element matched @element_name, %FALSE otherwise * * Since: 0.15.0 */ gboolean gdata_parser_string_from_json_member (JsonReader *reader, const gchar *member_name, GDataParserOptions options, gchar **output, gboolean *success, GError **error) { const gchar *text; const GError *child_error = NULL; /* Check if there's such element */ if (g_strcmp0 (json_reader_get_member_name (reader), member_name) != 0) { return FALSE; } /* Check if the output string has already been set. The JSON parser guarantees this can't happen. */ g_assert (!(options & P_NO_DUPES) || *output == NULL); /* Get the string and check it for NULLness or emptiness. Check for parser errors first. */ text = json_reader_get_string_value (reader); child_error = json_reader_get_error (reader); if (child_error != NULL) { *success = parser_error_from_json_error (reader, child_error, error); return TRUE; } else if ((options & P_REQUIRED && text == NULL) || (options & P_NON_EMPTY && text != NULL && *text == '\0')) { *success = gdata_parser_error_required_json_content_missing (reader, error); return TRUE; } else if (options & P_DEFAULT && (text == NULL || *text == '\0')) { text = ""; } /* Success! */ g_free (*output); *output = g_strdup (text); *success = TRUE; return TRUE; }
gboolean gdata_parser_error_duplicate_json_element (JsonReader *reader, GError **error) { const gchar *element_string = json_reader_get_member_name (reader); /* Translators: the parameter is the name of an JSON element. * * For example: * A singleton element (title) was duplicated. */ g_set_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROTOCOL_ERROR, _("A singleton element (%s) was duplicated."), element_string); return FALSE; }
gboolean gdata_parser_error_required_json_content_missing (JsonReader *reader, GError **error) { const gchar *element_string = json_reader_get_member_name (reader); /* Translators: the parameter is the name of an JSON element. * * For example: * A 'title' element was missing required content. */ g_set_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROTOCOL_ERROR, _("A \'%s\' element was missing required content."), element_string); return FALSE; }
gboolean gdata_parser_error_not_iso8601_format_json (JsonReader *reader, const gchar *actual_value, GError **error) { const gchar *element_string = json_reader_get_member_name (reader); g_set_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROTOCOL_ERROR, /* Translators: the first parameter is the name of an JSON element, * and the second parameter is the erroneous value (which was not in ISO 8601 format). * * For example: * The content of a 'uploaded' element ("2009-05-06 26:30Z") was not in ISO 8601 format. */ _("The content of a \'%s\' element (\"%s\") was not in ISO 8601 format."), element_string, actual_value); return FALSE; }
static gboolean reader_get_properties (JsonReader *reader, GDataFreebaseTopicObject *object, GError **error) { GDataFreebaseTopicValueArray *array; gboolean retval = TRUE; gint count, i; count = json_reader_count_members (reader); for (i = 0; i < count; i++) { GError *inner_error = NULL; const gchar *name; gchar *property; json_reader_read_element (reader, i); property = g_strdup (json_reader_get_member_name (reader)); name = property; /* Reverse properties start with !, display those as * regular properties, and skip that char */ if (name[0] == '!') name++; /* All Freebase properties and IDs start with '/' */ if (name[0] != '/') continue; /* Parse the value for this property, possibly with nested contents */ array = reader_create_value_array (reader, name, &inner_error); json_reader_end_element (reader); if (inner_error != NULL) { g_propagate_error (error, inner_error); retval = FALSE; break; } else if (array != NULL) { /* Takes ownership of array */ object_add_value (object, name, array); } g_free (property); } return retval; }
/* * gdata_parser_int64_time_from_json_member: * @reader: #JsonReader cursor object to read JSON node from * @element_name: the name of the element to parse * @options: a bitwise combination of parsing options from #GDataParserOptions, or %P_NONE * @output: (out caller-allocates): the return location for the parsed time value * @success: the return location for a value which is %TRUE if the time val was parsed successfully, %FALSE if an error was encountered, * and undefined if @element didn't match @element_name * @error: a #GError, or %NULL * * Gets the time value of @element if its name is @element_name, subject to various checks specified by @options. It expects the text content * of @element to be a date or time value in ISO 8601 format. The returned time value will be a UNIX timestamp (seconds since the epoch). * * If @element doesn't match @element_name, %FALSE will be returned, @error will be unset and @success will be unset. * * If @element matches @element_name but one of the checks specified by @options fails, %TRUE will be returned, @error will be set to a * %GDATA_SERVICE_ERROR_PROTOCOL_ERROR error and @success will be set to %FALSE. * * If @element matches @element_name and all of the checks specified by @options pass, %TRUE will be returned, @error will be unset and * @success will be set to %TRUE. * * The reason for returning the success of the parsing in @success is so that calls to gdata_parser_int64_time_from_element() can be chained * together in a large "or" statement based on their return values, for the purposes of determining whether any of the calls matched * a given @element. If any of the calls to gdata_parser_int64_time_from_element() return %TRUE, the value of @success can be examined. * * Return value: %TRUE if @element matched @element_name, %FALSE otherwise * * Since: 0.15.0 */ gboolean gdata_parser_int64_time_from_json_member (JsonReader *reader, const gchar *member_name, GDataParserOptions options, gint64 *output, gboolean *success, GError **error) { const gchar *text; GTimeVal time_val; const GError *child_error = NULL; /* Check if there's such element */ if (g_strcmp0 (json_reader_get_member_name (reader), member_name) != 0) { return FALSE; } /* Check if the output time val has already been set. The JSON parser guarantees this can't happen. */ g_assert (!(options & P_NO_DUPES) || *output == -1); /* Get the string and check it for NULLness. Check for errors first. */ text = json_reader_get_string_value (reader); child_error = json_reader_get_error (reader); if (child_error != NULL) { *success = parser_error_from_json_error (reader, child_error, error); return TRUE; } else if (options & P_REQUIRED && (text == NULL || *text == '\0')) { *success = gdata_parser_error_required_json_content_missing (reader, error); return TRUE; } /* Attempt to parse the string as a GTimeVal */ if (g_time_val_from_iso8601 ((gchar*) text, &time_val) == FALSE) { *success = gdata_parser_error_not_iso8601_format_json (reader, text, error); return TRUE; } /* Success! */ *output = time_val.tv_sec; *success = TRUE; return TRUE; }
/* Save key/values on the table in the stack if the value is an * object or an array, it calls recursively the function again. * * @param L, pointer to the L with nil on top of it; * @param reader, pointed to the first element of main object; * * returns: the table in the stack with all json values */ static void build_table_from_json_reader (lua_State *L, JsonReader *reader) { const GError *err = json_reader_get_error (reader); if (err != NULL) { GRL_WARNING ("Error when building json: %s", err->message); return; } if (lua_isnil (L, -1)) { /* In the first execution of this recursive call, the main json object * does not have a member name. The nil is in the top of the stack and * it shall be converted to the table with json content */ lua_pop (L, 1); } else if (lua_istable (L, -1)) { const gchar *member_name = json_reader_get_member_name (reader); if (member_name) lua_pushstring (L, member_name); } else if (!lua_isnumber (L, -1)) { GRL_DEBUG ("getting value to either table or array"); return; } if (json_reader_is_object (reader)) { guint index_member = 0; guint num_members = json_reader_count_members (reader); lua_createtable (L, num_members, 0); for (index_member = 0; index_member < num_members; index_member++) { json_reader_read_element (reader, index_member); build_table_from_json_reader (L, reader); json_reader_end_element (reader); } } else if (json_reader_is_array (reader)) { guint index_element = 0; guint num_elements = json_reader_count_elements (reader); lua_createtable (L, num_elements, 0); for (index_element = 0; index_element < num_elements; index_element++) { json_reader_read_element (reader, index_element); lua_pushinteger (L, index_element + 1); build_table_from_json_reader (L, reader); json_reader_end_element (reader); } } else if (json_reader_is_value (reader)) { if (json_reader_get_null_value (reader)) { lua_pushnil (L); } else { /* value of the element */ JsonNode *value = json_reader_get_value (reader); switch (json_node_get_value_type (value)) { case G_TYPE_STRING: lua_pushstring (L, json_reader_get_string_value (reader)); break; case G_TYPE_INT64: lua_pushinteger (L, json_reader_get_int_value (reader)); break; case G_TYPE_DOUBLE: lua_pushnumber (L, json_reader_get_double_value (reader)); break; case G_TYPE_BOOLEAN: lua_pushnumber (L, json_reader_get_boolean_value (reader)); break; default: GRL_DEBUG ("'%d' (json-node-type) is not being handled", (gint) json_node_get_value_type (value)); lua_pushnil (L); } } } if (lua_gettop (L) > 3) { /* save this key/value on previous table */ lua_settable (L, -3); } }
static gboolean parse_json (GDataParsable *parsable, JsonReader *reader, gpointer user_data, GError **error) { gboolean success = TRUE; gchar *next_uri = NULL; /* JSON format: https://developers.google.com/drive/v2/reference/files/list */ if (gdata_parser_string_from_json_member (reader, "nextLink", P_DEFAULT, &next_uri, &success, error) == TRUE) { if (success && next_uri != NULL && next_uri[0] != '\0') { GDataLink *_link; _link = gdata_link_new (next_uri, "http://www.iana.org/assignments/relation/next"); _gdata_feed_add_link (GDATA_FEED (parsable), _link); g_object_unref (_link); } g_free (next_uri); return success; } else if (g_strcmp0 (json_reader_get_member_name (reader), "items") == 0) { guint i, elements; if (json_reader_is_array (reader) == FALSE) { g_set_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROTOCOL_ERROR, /* Translators: the parameter is an error message */ _("Error parsing JSON: %s"), "JSON node ‘items’ is not an array."); return FALSE; } /* Loop through the elements array. */ for (i = 0, elements = (guint) json_reader_count_elements (reader); success && i < elements; i++) { GDataEntry *entry = NULL; GError *child_error = NULL; GType entry_type = G_TYPE_INVALID; gchar *kind = NULL; gchar *mime_type = NULL; json_reader_read_element (reader, i); if (json_reader_is_object (reader) == FALSE) { g_set_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROTOCOL_ERROR, /* Translators: the parameter is an error message */ _("Error parsing JSON: %s"), "JSON node inside ‘items’ is not an object"); success = FALSE; goto continuation; } get_kind_and_mime_type (reader, &kind, &mime_type, &child_error); if (child_error != NULL) { g_propagate_error (error, child_error); success = FALSE; goto continuation; } if (g_strcmp0 (kind, "drive#file") == 0) { entry_type = gdata_documents_utils_get_type_from_content_type (mime_type); } else { g_warning ("%s files are not handled yet", kind); } if (entry_type == G_TYPE_INVALID) goto continuation; entry = GDATA_ENTRY (_gdata_parsable_new_from_json_node (entry_type, reader, NULL, error)); /* Call the progress callback in the main thread */ _gdata_feed_call_progress_callback (GDATA_FEED (parsable), user_data, entry); _gdata_feed_add_entry (GDATA_FEED (parsable), entry); continuation: g_clear_object (&entry); g_free (kind); g_free (mime_type); json_reader_end_element (reader); } return success; } return GDATA_PARSABLE_CLASS (gdata_documents_feed_parent_class)->parse_json (parsable, reader, user_data, error); }