static void on_web_socket_message(SoupWebsocketConnection *ws, SoupWebsocketDataType type, GBytes *message, void *user_data) { const gchar *data; gsize len; data = g_bytes_get_data (message, &len); imgflo_debug("RECV: %.*s\n", (int)len, data); JsonParser *parser = json_parser_new(); gboolean success = json_parser_load_from_data(parser, data, len, NULL); if (success) { JsonNode *r = json_parser_get_root(parser); g_assert(JSON_NODE_HOLDS_OBJECT(r)); JsonObject *root = json_node_get_object(r); const gchar *protocol = json_object_get_string_member(root, "protocol"); const gchar *command = json_object_get_string_member(root, "command"); JsonNode *pnode = json_object_get_member(root, "payload"); JsonObject *payload = JSON_NODE_HOLDS_OBJECT(pnode) ? json_object_get_object_member(root, "payload") : NULL; UiConnection *ui = (UiConnection *)user_data; ui_connection_handle_message(ui, protocol, command, payload, ws); } else { imgflo_warning("Unable to parse WebSocket message as JSON"); } g_object_unref(parser); }
static GType object_peek_type (JsonNode *node) { JsonObject *obj; const gchar *type_str; if (!node || !JSON_NODE_HOLDS_OBJECT(node) || !(obj = json_node_get_object(node)) || !json_object_has_member(obj, "type") || !JSON_NODE_HOLDS_VALUE(json_object_get_member(obj, "type")) || !(type_str = json_object_get_string_member(obj, "type"))) { return FALSE; } if (!g_strcmp0(type_str, "note")) { return CATCH_TYPE_NOTE; } else if (!g_strcmp0(type_str, "image")) { return CATCH_TYPE_IMAGE; } else if (!g_strcmp0(type_str, "audio")) { return CATCH_TYPE_AUDIO; } else if (!g_strcmp0(type_str, "comment")) { return CATCH_TYPE_COMMENT; } else if (!g_strcmp0(type_str, "attachment")) { return CATCH_TYPE_ATTACHMENT; } else if (!g_strcmp0(type_str, "checkitem")) { return CATCH_TYPE_CHECK_ITEM; } return G_TYPE_NONE; }
void cometd_msg_set_boolean_member(JsonNode* node, const char* member, gboolean val) { g_assert(JSON_NODE_HOLDS_OBJECT (node)); JsonObject* obj = json_node_get_object(node); json_object_set_boolean_member(obj, member, val); }
/** * Returns a cometd_advice pointer that should be free'd by the caller. * Returns NULL if advice cannot be found. * * See also: http://svn.cometd.com/trunk/bayeux/bayeux.html#toc_32 */ cometd_advice* cometd_msg_advice(JsonNode* node) { g_return_val_if_fail(JSON_NODE_HOLDS_OBJECT (node), NULL); JsonObject* obj = json_node_get_object(node); cometd_advice* advice = NULL; JsonObject* advice_obj = NULL; if (json_object_has_member(obj, COMETD_MSG_ADVICE_FIELD)) advice_obj = json_object_get_object_member(obj, COMETD_MSG_ADVICE_FIELD); if (!advice_obj) return NULL; const char* reconnect = json_object_get_string_member(advice_obj, "reconnect"); const guint64 interval = json_object_get_int_member(advice_obj, "interval"); if (reconnect || interval) { advice = cometd_advice_new(); advice->interval = interval; if (strcmp("none", reconnect) == 0) { advice->reconnect = COMETD_RECONNECT_NONE; } else if (strcmp("handshake", reconnect) == 0) { advice->reconnect = COMETD_RECONNECT_HANDSHAKE; } else if (strcmp("retry", reconnect) == 0) { advice->reconnect = COMETD_RECONNECT_RETRY; } } return advice; }
void cometd_msg_set_advice(JsonNode* msg, const cometd_advice* advice) { g_return_if_fail(JSON_NODE_HOLDS_OBJECT (msg)); if (!advice) return; JsonObject* advice_obj = json_object_new(); char* reconnect = NULL; switch (advice->reconnect) { case COMETD_RECONNECT_NONE: reconnect = "none"; break; case COMETD_RECONNECT_RETRY: reconnect = "retry"; break; case COMETD_RECONNECT_HANDSHAKE: reconnect = "handshake"; break; } json_object_set_string_member(advice_obj, "reconnect", reconnect); json_object_set_int_member(advice_obj, "interval", advice->interval); JsonObject* obj = json_node_get_object(msg); json_object_set_object_member(obj, COMETD_MSG_ADVICE_FIELD, advice_obj); }
/** * json_reader_count_members: * @reader: a #JsonReader * * Counts the members of the current position, if @reader is * positioned on an object * * Return value: the number of members, or -1. In case of failure * the #JsonReader is set in an error state * * Since: 0.12 */ gint json_reader_count_members (JsonReader *reader) { JsonReaderPrivate *priv; g_return_val_if_fail (JSON_IS_READER (reader), -1); priv = reader->priv; if (priv->current_node == NULL) { json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE, _("No node available at the current position")); return -1; } if (!JSON_NODE_HOLDS_OBJECT (priv->current_node)) { json_reader_set_error (reader, JSON_READER_ERROR_NO_OBJECT, _("The current position holds a '%s' and not an object"), json_node_type_get_name (JSON_NODE_TYPE (priv->current_node))); return -1; } return json_object_get_size (json_node_get_object (priv->current_node)); }
static gboolean parse_review (AsReview *review, const gchar *our_username, JsonNode *node) { JsonObject *object; gint64 star_rating; g_autofree gchar *id_string = NULL; if (!JSON_NODE_HOLDS_OBJECT (node)) return FALSE; object = json_node_get_object (node); if (g_strcmp0 (our_username, json_object_get_string_member (object, "reviewer_username")) == 0) as_review_add_flags (review, AS_REVIEW_FLAG_SELF); as_review_set_reviewer_name (review, json_object_get_string_member (object, "reviewer_displayname")); as_review_set_summary (review, json_object_get_string_member (object, "summary")); as_review_set_description (review, json_object_get_string_member (object, "review_text")); as_review_set_version (review, json_object_get_string_member (object, "version")); star_rating = json_object_get_int_member (object, "rating"); if (star_rating > 0) as_review_set_rating (review, (gint) (star_rating * 20 - 10)); as_review_set_date (review, parse_date_time (json_object_get_string_member (object, "date_created"))); id_string = g_strdup_printf ("%" G_GINT64_FORMAT, json_object_get_int_member (object, "id")); as_review_add_metadata (review, "ubuntu-id", id_string); return TRUE; }
static gboolean catch_space_load_from_json (CatchResource *resource, JsonNode *node, GError **error) { CatchSpace *space = (CatchSpace *)resource; JsonObject *obj; ENTRY; g_return_val_if_fail(CATCH_IS_SPACE(space), FALSE); g_return_val_if_fail(node != NULL, FALSE); if (CATCH_RESOURCE_CLASS(catch_space_parent_class)->load_from_json) { if (!CATCH_RESOURCE_CLASS(catch_space_parent_class)-> load_from_json(resource, node, error)) { RETURN(FALSE); } } if (JSON_NODE_HOLDS_OBJECT(node) && (obj = json_node_get_object(node))) { if (json_object_has_member(obj, "name") && JSON_NODE_HOLDS_VALUE(json_object_get_member(obj, "name"))) { catch_space_set_name(CATCH_SPACE(resource), json_object_get_string_member(obj, "name")); } } RETURN(TRUE); }
static gboolean parse_httpstream_response (CockpitChannelResponse *chesp, JsonObject *object, gint64 *status, const gchar **reason) { JsonNode *node; if (!cockpit_json_get_int (object, "status", 200, status) || !cockpit_json_get_string (object, "reason", NULL, reason)) { g_warning ("%s: received invalid httpstream response", chesp->logname); return FALSE; } node = json_object_get_member (object, "headers"); if (node) { if (!JSON_NODE_HOLDS_OBJECT (node)) { g_warning ("%s: received invalid httpstream headers", chesp->logname); return FALSE; } json_object_foreach_member (json_node_get_object (node), object_to_headers, chesp->headers); } return TRUE; }
/** * Returns true if the JsonNode is an object and has a member * with the `data` attribute. */ gboolean cometd_msg_has_data(JsonNode* node) { g_return_val_if_fail(JSON_NODE_HOLDS_OBJECT (node), FALSE); gboolean ret; JsonObject* obj = json_node_get_object(node); ret = json_object_has_member(obj, COMETD_MSG_DATA_FIELD); return ret; }
/* Import play list from a json object */ void plist_import_from_json( plist_t *pl, JsonArray *js_plist ) { int num_songs = json_array_get_length(js_plist); for ( int i = 0; i < num_songs; ++i ) { JsonNode *js_song_node = json_array_get_element(js_plist, i); if (!js_song_node) continue; if (!JSON_NODE_HOLDS_OBJECT(js_song_node)) continue; JsonObject *js_song = json_node_get_object(js_song_node); const char *name = js_get_string(js_song, "name", NULL); if (!name) continue; song_metadata_t metadata = SONG_METADATA_EMPTY; const char *title = js_get_string(js_song, "title", NULL); if (title) metadata.m_title = title; metadata.m_len = js_get_int(js_song, "length", 0); metadata.m_start_time = js_get_int(js_song, "start_time", -1); metadata.m_end_time = js_get_int(js_song, "end_time", -1); song_info_t *si = NULL; JsonObject *js_si = js_get_obj(js_song, "song_info"); if (js_si) { si = si_new(); si_set_artist (si, js_get_string(js_si, "artist", "")); si_set_name (si, js_get_string(js_si, "name", "")); si_set_album (si, js_get_string(js_si, "album", "")); si_set_year (si, js_get_string(js_si, "year", "")); si_set_genre (si, js_get_string(js_si, "genre", "")); si_set_comments (si, js_get_string(js_si, "comments", "")); si_set_track (si, js_get_string(js_si, "track", "")); } bool_t is_static_info = js_get_int(js_song, "static_info", 0); if (is_static_info) metadata.m_song_info = si; song_t *s = fu_is_prefixed(name) ? song_new_from_uri(name, &metadata) : song_new_from_file(name, &metadata); if (s) { if (!is_static_info && si) song_set_info(s, si); plist_add_song(pl, s, -1); } } }
/** * Returns the client id of the message as a new string */ char* cometd_msg_client_id(JsonNode* node) { g_return_val_if_fail(JSON_NODE_HOLDS_OBJECT (node), NULL); const char* client_id; JsonObject* obj = json_node_get_object(node); client_id = json_object_get_string_member(obj, COMETD_MSG_CLIENT_ID_FIELD); return strdup(client_id); }
/** * json_reader_is_object: * @reader: a #JsonReader * * Checks whether the @reader is currently on an object * * Return value: %TRUE if the #JsonReader is on an object, and %FALSE * otherwise * * Since: 0.12 */ gboolean json_reader_is_object (JsonReader *reader) { g_return_val_if_fail (JSON_IS_READER (reader), FALSE); json_reader_return_val_if_error_set (reader, FALSE); if (reader->priv->current_node == NULL) return FALSE; return JSON_NODE_HOLDS_OBJECT (reader->priv->current_node); }
/** * Returns the channel of the message as a new string */ char* cometd_msg_channel(JsonNode* node) { g_return_val_if_fail(JSON_NODE_HOLDS_OBJECT (node), NULL); const char* channel; JsonObject* obj = json_node_get_object(node); channel = json_object_get_string_member(obj, COMETD_MSG_CHANNEL_FIELD); return channel != NULL ? strdup(channel) : NULL; }
static gboolean parse_option_file_or_data (CockpitChannel *self, JsonObject *options, const gchar *option, const gchar **file, const gchar **data) { JsonObject *object; JsonNode *node; g_assert (file != NULL); g_assert (data != NULL); node = json_object_get_member (options, option); if (!node) { *file = NULL; *data = NULL; return TRUE; } if (!JSON_NODE_HOLDS_OBJECT (node)) { cockpit_channel_fail (self, "protocol-error", "invalid \"%s\" tls option for channel", option); return FALSE; } object = json_node_get_object (node); if (!cockpit_json_get_string (object, "file", NULL, file)) { cockpit_channel_fail (self, "protocol-error", "invalid \"file\" %s option for channel", option); } else if (!cockpit_json_get_string (object, "data", NULL, data)) { cockpit_channel_fail (self, "protocol-error", "invalid \"data\" %s option for channel", option); } else if (!*file && !*data) { cockpit_channel_fail (self, "not-supported", "missing or unsupported \"%s\" option for channel", option); } else if (*file && *data) { cockpit_channel_fail (self, "protocol-error", "cannot specify both \"file\" and \"data\" in \"%s\" option for channel", option); } else { return TRUE; } return FALSE; }
static const gchar * parse_option_file_or_data (JsonObject *options, const gchar *option, const gchar **file, const gchar **data) { JsonObject *object; JsonNode *node; g_assert (file != NULL); g_assert (data != NULL); node = json_object_get_member (options, option); if (!node) { *file = NULL; *data = NULL; return NULL; } if (!JSON_NODE_HOLDS_OBJECT (node)) { g_warning ("invalid \"%s\" tls option for channel", option); return "protocol-error"; } object = json_node_get_object (node); if (!cockpit_json_get_string (object, "file", NULL, file)) { g_warning ("invalid \"file\" %s option for channel", option); return "protocol-error"; } else if (!cockpit_json_get_string (object, "data", NULL, data)) { g_warning ("invalid \"data\" %s option for channel", option); return "protocol-error"; } else if (!*file && !*data) { g_warning ("missing or unsupported \"%s\" option for channel", option); return "not-supported"; } else if (*file && *data) { g_warning ("cannot specify both \"file\" and \"data\" in \"%s\" option for channel", option); return "protocol-error"; } return NULL; }
static void snra_json_node_into_val (JsonNode *element_node, GValue *v) { if (JSON_NODE_HOLDS_OBJECT (element_node)) { GstStructure *child = snra_json_to_gst_structure (element_node); g_value_init (v, GST_TYPE_STRUCTURE); gst_value_set_structure (v, child); } else if (JSON_NODE_HOLDS_ARRAY (element_node)) { JsonArray *arr = json_node_get_array (element_node); g_value_init (v, GST_TYPE_ARRAY); json_array_foreach_element (arr, (JsonArrayForeach) snra_json_array_add_to_val, v); } else { json_node_get_value (element_node, v); } }
GstStructure * snra_json_to_gst_structure (JsonNode * root) { GstStructure *s = NULL; JsonObject *o; if (!JSON_NODE_HOLDS_OBJECT (root)) return NULL; s = gst_structure_new ("json", NULL, NULL); o = json_node_get_object (root); json_object_foreach_member (o, (JsonObjectForeach) snra_gst_struct_from_object, s); return s; }
/** * json_reader_count_members: * @reader: a #JsonReader * * Counts the members of the current position, if @reader is * positioned on an object * * Return value: the number of members, or -1. In case of failure * the #JsonReader is set in an error state * * Since: 0.12 */ gint json_reader_count_members (JsonReader *reader) { JsonReaderPrivate *priv; g_return_val_if_fail (JSON_IS_READER (reader), -1); priv = reader->priv; if (priv->current_node == NULL) return -1; if (!JSON_NODE_HOLDS_OBJECT (priv->current_node)) return -1; return json_object_get_size (json_node_get_object (priv->current_node)); }
/** * json_object_get_object_member: * @object: a #JsonObject * @member_name: the name of the member * * Convenience function that retrieves the object * stored in @member_name of @object * * See also: json_object_get_member() * * Return value: (transfer none): the object inside the object's member * * Since: 0.8 */ JsonObject * json_object_get_object_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_OBJECT (node) || JSON_NODE_HOLDS_NULL (node), NULL); if (JSON_NODE_HOLDS_NULL (node)) return NULL; return json_node_get_object (node); }
/** * json_array_get_object_element: * @array: a #JsonArray * @index_: the index of the element to retrieve * * Conveniently retrieves the object from the element at @index_ * inside @array * * See also: json_array_get_element(), json_node_get_object() * * Return value: (transfer none): the object * * Since: 0.8 */ JsonObject * json_array_get_object_element (JsonArray *array, guint index_) { JsonNode *node; g_return_val_if_fail (array != NULL, NULL); g_return_val_if_fail (index_ < array->elements->len, NULL); node = g_ptr_array_index (array->elements, index_); g_return_val_if_fail (node != NULL, NULL); g_return_val_if_fail (JSON_NODE_HOLDS_OBJECT (node) || JSON_NODE_HOLDS_NULL (node), NULL); if (JSON_NODE_HOLDS_NULL (node)) return NULL; return json_node_get_object (node); }
GHashTable * json_ghashtable_deserialize (JsonNode *node, GError **error) { GHashTable *table = NULL; GList *k; GList *keys; JsonNode *node_value; JsonObject *object; gchar *value; if (!node || !JSON_NODE_HOLDS_OBJECT (node)) { g_set_error_literal (error, JSON_READER_ERROR, JSON_READER_ERROR_NO_OBJECT, "Expected JSON object"); return table; } object = json_node_get_object (node); keys = json_object_get_members (object); table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); for (k = keys; k ; k = g_list_next (k)) { node_value = json_object_get_member (object, k->data); if (!JSON_NODE_HOLDS_VALUE (node_value) || (value = json_node_dup_string (node_value)) == NULL) { g_set_error_literal (error, JSON_READER_ERROR, JSON_READER_ERROR_INVALID_TYPE, "Expected JSON string"); g_hash_table_unref (table); table = NULL; break; } else { g_hash_table_insert (table, g_strdup (k->data), value); } } g_list_free (keys); json_object_unref (object); return table; }
static char * writer_filter (JsonNode *element) { JsonObject *object; const char *department; if (!JSON_NODE_HOLDS_OBJECT (element)) { return NULL; } object = json_node_get_object (element); department = json_object_get_string_member (object, "department"); if (g_ascii_strcasecmp (department, "Writing") != 0) { return NULL; } return g_strdup (json_object_get_string_member (object, "name")); }
static char * neutral_backdrop_filter (JsonNode *node) { JsonObject *object; const char *language; if (!JSON_NODE_HOLDS_OBJECT (node)) { return NULL; } object = json_node_get_object (node); language = json_object_get_string_member (object, "iso_639_1"); /* Language-neutral backdrops only */ if (language == NULL) { return g_strdup (json_object_get_string_member (object, "file_path")); } return NULL; }
static gboolean read_config_file(AppContext *app, GError **err) { JsonNode *root; JsonParser *parser; parser = json_parser_new (); if (!json_parser_load_from_file (parser, app->config_filename, err)) { g_object_unref(parser); return FALSE; } root = json_parser_get_root(parser); if (JSON_NODE_HOLDS_OBJECT(root)) { JsonNode *value_node; JsonObject *root_obj = json_node_get_object(root); value_node = json_object_get_member(root_obj, "extensionPort"); if (value_node && JSON_NODE_HOLDS_VALUE(value_node)) { app->http_port = json_node_get_int(value_node); } value_node = json_object_get_member(root_obj, "httpRootPath"); if (value_node && JSON_NODE_HOLDS_VALUE(value_node)) { GFile *base; GFile *http_root; GFile *config; char *path = json_node_dup_string(value_node); config = g_file_new_for_path(app->config_filename); base = g_file_get_parent(config); g_object_unref(config); g_free(app->http_root); http_root = g_file_resolve_relative_path (base, path); g_free(path); g_object_unref(base); if (http_root) { app->http_root = g_file_get_path(http_root); g_debug("HTTP root: %s", app->http_root); g_object_unref(http_root); } } } g_object_unref(parser); return TRUE; }
static void test_response_data (gconstpointer data) { JsonParser *parser; JsonNode *node; JsonObject *object; double latitude, longitude; parser = json_parser_new (); g_assert (json_parser_load_from_data (parser, (const char *) data, -1, NULL)); node = json_parser_get_root (parser); g_assert (JSON_NODE_HOLDS_OBJECT (node)); object = json_node_get_object (node); g_assert (object != NULL); g_assert (json_object_has_member (object, "ip")); g_assert (strcmp (json_object_get_string_member (object, "ip"), "213.243.180.91") == 0); g_assert (json_object_has_member (object, "latitude")); latitude = json_object_get_double_member (object, "latitude"); g_assert (latitude > 60.1755 && latitude <= 60.1756); g_assert (json_object_has_member (object, "longitude")); longitude = json_object_get_double_member (object, "longitude"); g_assert (longitude >= 24.9342 && longitude < 24.9343); g_assert (json_object_has_member (object, "city")); g_assert (strcmp (json_object_get_string_member (object, "city"), "Helsinki") == 0); g_assert (json_object_has_member (object, "region_name")); g_assert (strcmp (json_object_get_string_member (object, "region_name"), "Southern Finland") == 0); g_assert (json_object_has_member (object, "country_name")); g_assert (strcmp (json_object_get_string_member (object, "country_name"), "Finland") == 0); if (json_object_has_member (object, "accuracy")) g_assert (strcmp (json_object_get_string_member (object, "accuracy"), "city") == 0); if (json_object_has_member (object, "timezone")) g_assert (strcmp (json_object_get_string_member (object, "timezone"), "Europe/Helsinki") == 0); g_object_unref (parser); }
static JsonParser * parse_result (const gchar *response, const gchar *response_type, GError **error) { g_autoptr(JsonParser) parser = NULL; g_autoptr(GError) error_local = NULL; if (response_type == NULL) { g_set_error_literal (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_INVALID_FORMAT, "snapd returned no content type"); return NULL; } if (g_strcmp0 (response_type, "application/json") != 0) { g_set_error (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_INVALID_FORMAT, "snapd returned unexpected content type %s", response_type); return NULL; } parser = json_parser_new (); if (!json_parser_load_from_data (parser, response, -1, &error_local)) { g_set_error (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_INVALID_FORMAT, "Unable to parse snapd response: %s", error_local->message); return NULL; } if (!JSON_NODE_HOLDS_OBJECT (json_parser_get_root (parser))) { g_set_error_literal (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_INVALID_FORMAT, "snapd response does is not a valid JSON object"); return NULL; } return g_object_ref (parser); }
static gboolean parse_review_entry (JsonNode *node, const gchar **package_name, Histogram *histogram) { JsonObject *object; const gchar *name = NULL, *histogram_text = NULL; if (!JSON_NODE_HOLDS_OBJECT (node)) return FALSE; object = json_node_get_object (node); name = json_object_get_string_member (object, "package_name"); histogram_text = json_object_get_string_member (object, "histogram"); if (!name || !histogram_text) return FALSE; if (!parse_histogram (histogram_text, histogram)) return FALSE; *package_name = name; return TRUE; }
/** * json_array_get_null_element: * @array: a #JsonArray * @index_: the index of the element to retrieve * * Conveniently retrieves whether the element at @index_ is set to null * * See also: json_array_get_element(), JSON_NODE_TYPE(), %JSON_NODE_NULL * * Return value: %TRUE if the element is null * * Since: 0.8 */ gboolean json_array_get_null_element (JsonArray *array, guint index_) { JsonNode *node; g_return_val_if_fail (array != NULL, FALSE); g_return_val_if_fail (index_ < array->elements->len, FALSE); node = g_ptr_array_index (array->elements, index_); g_return_val_if_fail (node != NULL, FALSE); if (JSON_NODE_HOLDS_NULL (node)) return TRUE; if (JSON_NODE_HOLDS_ARRAY (node)) return json_node_get_array (node) == NULL; if (JSON_NODE_HOLDS_OBJECT (node)) return json_node_get_object (node) == NULL; return FALSE; }
/** * json_object_get_null_member: * @object: a #JsonObject * @member_name: the name of the member * * Convenience function that checks whether the value * stored in @member_name of @object is null * * See also: json_object_get_member() * * Return value: %TRUE if the value is null * * Since: 0.8 */ gboolean json_object_get_null_member (JsonObject *object, const gchar *member_name) { JsonNode *node; g_return_val_if_fail (object != NULL, FALSE); g_return_val_if_fail (member_name != NULL, FALSE); node = object_get_member_internal (object, member_name); g_return_val_if_fail (node != NULL, FALSE); if (JSON_NODE_HOLDS_NULL (node)) return TRUE; if (JSON_NODE_HOLDS_OBJECT (node)) return json_node_get_object (node) == NULL; if (JSON_NODE_HOLDS_ARRAY (node)) return json_node_get_array (node) == NULL; return FALSE; }