/** * json_array_add_null_element: * @array: a #JsonArray * * Conveniently adds a null element into @array * * See also: json_array_add_element(), %JSON_NODE_NULL * * Since: 0.8 */ void json_array_add_null_element (JsonArray *array) { g_return_if_fail (array != NULL); g_ptr_array_add (array->elements, json_node_init_null (json_node_alloc ())); }
void _cockpit_assert_json_eq_msg (const char *domain, const char *file, int line, const char *func, JsonObject *object, const gchar *expect) { GError *error = NULL; JsonNode *node; JsonNode *exnode; gchar *escaped; gchar *msg; node = json_node_init_object (json_node_alloc (), object); exnode = cockpit_json_parse (expect, -1, &error); if (error) g_assertion_message_error (domain, file, line, func, "error", error, 0, 0); g_assert (exnode); if (!cockpit_json_equal (exnode, node)) { escaped = cockpit_json_write (node, NULL); msg = g_strdup_printf ("%s != %s", escaped, expect); g_assertion_message (domain, file, line, func, msg); g_free (escaped); g_free (msg); } json_node_free (node); json_node_free (exnode); }
/** * json_array_add_boolean_element: * @array: a #JsonArray * @value: a boolean value * * Conveniently adds a boolean @value into @array * * See also: json_array_add_element(), json_node_set_boolean() * * Since: 0.8 */ void json_array_add_boolean_element (JsonArray *array, gboolean value) { g_return_if_fail (array != NULL); g_ptr_array_add (array->elements, json_node_init_boolean (json_node_alloc (), value)); }
/** * json_array_add_double_element: * @array: a #JsonArray * @value: a floating point value * * Conveniently adds a floating point @value into @array * * See also: json_array_add_element(), json_node_set_double() * * Since: 0.8 */ void json_array_add_double_element (JsonArray *array, gdouble value) { g_return_if_fail (array != NULL); g_ptr_array_add (array->elements, json_node_init_double (json_node_alloc (), value)); }
/** * json_node_new: (constructor) * @type: a #JsonNodeType * * Creates a new #JsonNode of @type. * * This is a convenience function for json_node_alloc() and json_node_init(), * and it's the equivalent of: * * |[<!-- language="C" --> json_node_init (json_node_alloc (), type); * ]| * * Return value: (transfer full): the newly created #JsonNode */ JsonNode * json_node_new (JsonNodeType type) { g_return_val_if_fail (type >= JSON_NODE_OBJECT && type <= JSON_NODE_NULL, NULL); return json_node_init (json_node_alloc (), type); }
/** * json_object_set_null_member: * @object: a #JsonObject * @member_name: the name of the member * * Convenience function for setting a null @value of * @member_name inside @object. * * See also: json_object_set_member() * * Since: 0.8 */ void json_object_set_null_member (JsonObject *object, const gchar *member_name) { g_return_if_fail (object != NULL); g_return_if_fail (member_name != NULL); object_set_member_internal (object, member_name, json_node_init_null (json_node_alloc ())); }
/** * json_object_set_boolean_member: * @object: a #JsonObject * @member_name: the name of the member * @value: the value of the member * * Convenience function for setting a boolean @value of * @member_name inside @object. * * See also: json_object_set_member() * * Since: 0.8 */ void json_object_set_boolean_member (JsonObject *object, const gchar *member_name, gboolean value) { g_return_if_fail (object != NULL); g_return_if_fail (member_name != NULL); object_set_member_internal (object, member_name, json_node_init_boolean (json_node_alloc (), value)); }
void snarf_alert_add_double_field(snarf_alert_t *alert, const char *name, double value) { JsonObject * rootobj = json_node_get_object (alert->msg); JsonObject * bodyobj = json_object_get_object_member(rootobj,"body"); JsonNode * doublenode = json_node_alloc(); doublenode=json_node_init_double(doublenode,value); json_object_set_member(bodyobj,name,doublenode); }
void snarf_alert_add_int_field(snarf_alert_t *alert, const char *name, int64_t value) { JsonObject * rootobj = json_node_get_object (alert->msg); JsonObject * bodyobj = json_object_get_object_member(rootobj,"body"); JsonNode * intnode = json_node_alloc(); intnode=json_node_init_int(intnode,value); json_object_set_member(bodyobj,name,intnode); }
void snarf_alert_add_text_field(snarf_alert_t *alert, const char *name, const char *value) { // Add text field to body JsonNode *node; JsonObject * rootobj = json_node_get_object (alert->msg); JsonObject * bodyobj = json_object_get_object_member(rootobj,"body"); JsonNode * stringnode = json_node_alloc(); stringnode=json_node_init_string(stringnode,value); json_object_set_member(bodyobj,name,stringnode); }
/** * json_array_add_string_element: * @array: a #JsonArray * @value: a string value * * Conveniently adds a string @value into @array * * See also: json_array_add_element(), json_node_set_string() * * Since: 0.8 */ void json_array_add_string_element (JsonArray *array, const gchar *value) { JsonNode *node; g_return_if_fail (array != NULL); node = json_node_alloc (); if (value != NULL && *value != '\0') json_node_init_string (node, value); else json_node_init_null (node); g_ptr_array_add (array->elements, node); }
void snarf_alert_add_ip_field_v4(snarf_alert_t *alert, const char *name, uint32_t value) { // Add IP field to body JsonNode *node; JsonObject * rootobj = json_node_get_object (alert->msg); JsonObject * bodyobj = json_object_get_object_member(rootobj,"body"); JsonNode * stringnode = json_node_alloc(); struct in_addr ip; ip.s_addr=htonl(value); stringnode=json_node_init_string(stringnode,inet_ntoa(ip)); json_object_set_member(bodyobj,name,stringnode); }
/** * json_object_set_string_member: * @object: a #JsonObject * @member_name: the name of the member * @value: the value of the member * * Convenience function for setting a string @value of * @member_name inside @object. * * See also: json_object_set_member() * * Since: 0.8 */ void json_object_set_string_member (JsonObject *object, const gchar *member_name, const gchar *value) { JsonNode *node; g_return_if_fail (object != NULL); g_return_if_fail (member_name != NULL); node = json_node_alloc (); if (value != NULL) json_node_init_string (node, value); else json_node_init_null (node); object_set_member_internal (object, member_name, node); }
/** * json_array_add_object_element: * @array: a #JsonArray * @value: (transfer full): a #JsonObject * * Conveniently adds an object into @array. The @array takes ownership * of the newly added #JsonObject * * See also: json_array_add_element(), json_node_take_object() * * Since: 0.8 */ void json_array_add_object_element (JsonArray *array, JsonObject *value) { JsonNode *node; g_return_if_fail (array != NULL); node = json_node_alloc (); if (value != NULL) { json_node_init_object (node, value); json_object_unref (value); } else json_node_init_null (node); g_ptr_array_add (array->elements, node); }
/** * json_object_set_array_member: * @object: a #JsonObject * @member_name: the name of the member * @value: (transfer full): the value of the member * * Convenience function for setting an array @value of * @member_name inside @object. * * The @object will take ownership of the passed #JsonArray * * See also: json_object_set_member() * * Since: 0.8 */ void json_object_set_array_member (JsonObject *object, const gchar *member_name, JsonArray *value) { JsonNode *node; g_return_if_fail (object != NULL); g_return_if_fail (member_name != NULL); node = json_node_alloc (); if (value != NULL) { json_node_init_array (node, value); json_array_unref (value); } else json_node_init_null (node); object_set_member_internal (object, member_name, node); }
/** * json_node_copy: * @node: a #JsonNode * * Copies @node. If the node contains complex data types, their reference * counts are increased, regardless of whether the node is mutable or * immutable. * * The copy will be immutable if, and only if, @node is immutable. However, * there should be no need to copy an immutable node. * * Return value: (transfer full): the copied #JsonNode */ JsonNode * json_node_copy (JsonNode *node) { JsonNode *copy; g_return_val_if_fail (JSON_NODE_IS_VALID (node), NULL); copy = json_node_alloc (); copy->type = node->type; copy->immutable = node->immutable; if (node->immutable) g_debug ("Copying immutable JsonNode %p", node); switch (copy->type) { case JSON_NODE_OBJECT: copy->data.object = json_node_dup_object (node); break; case JSON_NODE_ARRAY: copy->data.array = json_node_dup_array (node); break; case JSON_NODE_VALUE: if (node->data.value) copy->data.value = json_value_ref (node->data.value); break; case JSON_NODE_NULL: break; default: g_assert_not_reached (); } return copy; }
JsonNode * json_serialize_pspec (const GValue *real_value, GParamSpec *pspec) { JsonNode *retval = NULL; JsonNodeType node_type; switch (G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (real_value))) { /* JSON native types */ case G_TYPE_INT64: retval = json_node_init_int (json_node_alloc (), g_value_get_int64 (real_value)); break; case G_TYPE_BOOLEAN: retval = json_node_init_boolean (json_node_alloc (), g_value_get_boolean (real_value)); break; case G_TYPE_DOUBLE: retval = json_node_init_double (json_node_alloc (), g_value_get_double (real_value)); break; case G_TYPE_STRING: retval = json_node_init_string (json_node_alloc (), g_value_get_string (real_value)); break; /* auto-promoted types */ case G_TYPE_INT: retval = json_node_init_int (json_node_alloc (), g_value_get_int (real_value)); break; case G_TYPE_UINT: retval = json_node_init_int (json_node_alloc (), g_value_get_uint (real_value)); break; case G_TYPE_LONG: retval = json_node_init_int (json_node_alloc (), g_value_get_long (real_value)); break; case G_TYPE_ULONG: retval = json_node_init_int (json_node_alloc (), g_value_get_ulong (real_value)); break; case G_TYPE_UINT64: retval = json_node_init_int (json_node_alloc (), g_value_get_uint64 (real_value)); break; case G_TYPE_FLOAT: retval = json_node_init_double (json_node_alloc (), g_value_get_float (real_value)); break; case G_TYPE_CHAR: retval = json_node_alloc (); json_node_init_int (retval, g_value_get_schar (real_value)); break; case G_TYPE_UCHAR: retval = json_node_init_int (json_node_alloc (), g_value_get_uchar (real_value)); break; case G_TYPE_ENUM: retval = json_node_init_int (json_node_alloc (), g_value_get_enum (real_value)); break; case G_TYPE_FLAGS: retval = json_node_init_int (json_node_alloc (), g_value_get_flags (real_value)); break; /* complex types */ case G_TYPE_BOXED: if (G_VALUE_HOLDS (real_value, G_TYPE_STRV)) { gchar **strv = g_value_get_boxed (real_value); gint i, strv_len; JsonArray *array; strv_len = g_strv_length (strv); array = json_array_sized_new (strv_len); for (i = 0; i < strv_len; i++) { JsonNode *str = json_node_new (JSON_NODE_VALUE); json_node_set_string (str, strv[i]); json_array_add_element (array, str); } retval = json_node_init_array (json_node_alloc (), array); json_array_unref (array); } else if (json_boxed_can_serialize (G_VALUE_TYPE (real_value), &node_type)) { gpointer boxed = g_value_get_boxed (real_value); retval = json_boxed_serialize (G_VALUE_TYPE (real_value), boxed); } else g_warning ("Boxed type '%s' is not handled by JSON-GLib", g_type_name (G_VALUE_TYPE (real_value))); break; case G_TYPE_OBJECT: { GObject *object = g_value_get_object (real_value); retval = json_node_alloc (); if (object != NULL) { json_node_init (retval, JSON_NODE_OBJECT); json_node_take_object (retval, json_gobject_dump (object)); } else json_node_init_null (retval); } break; case G_TYPE_NONE: retval = json_node_new (JSON_NODE_NULL); break; default: g_warning ("Unsupported type `%s'", g_type_name (G_VALUE_TYPE (real_value))); break; } return retval; }
static JsonNode * builder_options_serialize_property (JsonSerializable *serializable, const gchar *property_name, const GValue *value, GParamSpec *pspec) { if (strcmp (property_name, "arch") == 0) { BuilderOptions *self = BUILDER_OPTIONS (serializable); JsonNode *retval = NULL; if (self->arch && g_hash_table_size (self->arch) > 0) { JsonObject *object; GHashTableIter iter; gpointer key, value; object = json_object_new (); g_hash_table_iter_init (&iter, self->arch); while (g_hash_table_iter_next (&iter, &key, &value)) { JsonNode *child = json_gobject_serialize (value); json_object_set_member (object, (char *)key, child); } retval = json_node_init_object (json_node_alloc (), object); json_object_unref (object); } return retval; } else if (strcmp (property_name, "env") == 0) { BuilderOptions *self = BUILDER_OPTIONS (serializable); JsonNode *retval = NULL; if (self->env && g_strv_length (self->env) > 0) { JsonObject *object; int i; object = json_object_new (); for (i = 0; self->env[i] != NULL; i++) { JsonNode *str = json_node_new (JSON_NODE_VALUE); const char *equal; g_autofree char *member = NULL; equal = strchr (self->env[i], '='); if (equal) { json_node_set_string (str, equal + 1); member = g_strndup (self->env[i], equal - self->env[i]); } else { json_node_set_string (str, ""); member = g_strdup (self->env[i]); } json_object_set_member (object, member, str); } retval = json_node_init_object (json_node_alloc (), object); json_object_unref (object); } return retval; } else return json_serializable_default_serialize_property (serializable, property_name, value, pspec); }
JsonNode * js_util_tojsonnode(js_State *state, int idx) { const char *s; JsonNode *node; JsonNode *tmp; JsonObject *object; JsonArray *array; unsigned int i, length; node = json_node_alloc(); if (js_isstring(state, idx)) { json_node_init_string(node, js_tostring(state, idx)); } else if (js_isnumber(state, idx)) { json_node_init_int(node, js_tointeger(state, idx)); } else if (js_isboolean(state, idx)) { json_node_init_boolean(node, js_toboolean(state, idx)); } else if (js_isarray(state, idx)) { length = js_getlength(state, idx); array = json_array_new(); json_node_init_array(node, array); for (i = 0; i < length; i++) { js_getindex(state, idx, i); tmp = js_util_tojsonnode(state, -1); if (tmp) json_array_add_element(array, tmp); js_pop(state, 1); } json_array_unref(array); } else if (js_isobject(state, idx)) { object = json_object_new(); json_node_init_object(node, object); js_pushiterator(state, idx, 1); while((s = js_nextiterator(state, -1)) != NULL) { if (idx > 0) js_getproperty(state, idx, s); else js_getproperty(state, idx - 1, s); tmp = js_util_tojsonnode(state, -1); if (tmp) json_object_set_member(object, s, tmp); js_pop(state, 1); } js_pop(state, 1); json_object_unref(object); } else { json_node_free(node); return NULL; } return node; }
static void send_meta (CockpitInternalMetrics *self) { JsonArray *metrics; JsonObject *metric; JsonObject *root; struct timeval now_timeval; gint64 now; gettimeofday (&now_timeval, NULL); now = timestamp_from_timeval (&now_timeval); root = json_object_new (); json_object_set_int_member (root, "timestamp", now); json_object_set_int_member (root, "now", now); json_object_set_int_member (root, "interval", self->interval); metrics = json_array_new (); for (int i = 0; i < self->n_metrics; i++) { MetricInfo *info = &self->metrics[i]; metric = json_object_new (); /* Name and derivation mode */ json_object_set_string_member (metric, "name", info->desc->name); if (info->derive) json_object_set_string_member (metric, "derive", info->derive); /* Instances */ if (info->desc->instanced) { GHashTableIter iter; gpointer key, value; int index; JsonArray *instances = json_array_new (); g_hash_table_iter_init (&iter, info->instances); index = 0; while (g_hash_table_iter_next (&iter, &key, &value)) { const gchar *name = key; InstanceInfo *inst = value; /* HACK: We can't use json_builder_add_string_value here since it turns empty strings into 'null' values inside arrays. https://bugzilla.gnome.org/show_bug.cgi?id=730803 */ { JsonNode *string_element = json_node_alloc (); json_node_init_string (string_element, name); json_array_add_element (instances, string_element); } inst->index = index++; } json_object_set_array_member (metric, "instances", instances); } /* Units and semantics */ json_object_set_string_member (metric, "units", info->desc->units); json_object_set_string_member (metric, "semantics", info->desc->semantics); json_array_add_object_element (metrics, metric); } json_object_set_array_member (root, "metrics", metrics); cockpit_metrics_send_meta (COCKPIT_METRICS (self), root, FALSE); json_object_unref (root); }
static void build_json (JsonBuilder *builder, GVariant *value) { const GVariantType *type; const GVariantType *element_type; g_variant_ref_sink (value); switch (g_variant_classify (value)) { case G_VARIANT_CLASS_BOOLEAN: json_builder_add_boolean_value (builder, g_variant_get_boolean (value)); break; case G_VARIANT_CLASS_BYTE: json_builder_add_int_value (builder, g_variant_get_byte (value)); break; case G_VARIANT_CLASS_INT16: json_builder_add_int_value (builder, g_variant_get_int16 (value)); break; case G_VARIANT_CLASS_UINT16: json_builder_add_int_value (builder, g_variant_get_uint16 (value)); break; case G_VARIANT_CLASS_INT32: json_builder_add_int_value (builder, g_variant_get_int32 (value)); break; case G_VARIANT_CLASS_UINT32: json_builder_add_int_value (builder, g_variant_get_uint32 (value)); break; case G_VARIANT_CLASS_INT64: json_builder_add_int_value (builder, g_variant_get_int64 (value)); break; case G_VARIANT_CLASS_UINT64: json_builder_add_int_value (builder, g_variant_get_uint64 (value)); break; case G_VARIANT_CLASS_HANDLE: json_builder_add_int_value (builder, g_variant_get_handle (value)); break; case G_VARIANT_CLASS_DOUBLE: json_builder_add_double_value (builder, g_variant_get_double (value)); break; case G_VARIANT_CLASS_STRING: /* explicit fall-through */ case G_VARIANT_CLASS_OBJECT_PATH: /* explicit fall-through */ case G_VARIANT_CLASS_SIGNATURE: { /* HACK: We can't use json_builder_add_string_value here since it turns empty strings into 'null' values inside arrays. https://bugzilla.gnome.org/show_bug.cgi?id=730803 */ JsonNode *string_element = json_node_alloc (); json_node_init_string (string_element, g_variant_get_string (value, NULL)); json_builder_add_value (builder, string_element); } break; case G_VARIANT_CLASS_VARIANT: build_json_variant (builder, value); break; case G_VARIANT_CLASS_ARRAY: type = g_variant_get_type (value); element_type = g_variant_type_element (type); if (g_variant_type_is_dict_entry (element_type)) build_json_dictionary (builder, element_type, value); else build_json_array_or_tuple (builder, value); break; case G_VARIANT_CLASS_TUPLE: build_json_array_or_tuple (builder, value); break; case G_VARIANT_CLASS_DICT_ENTRY: case G_VARIANT_CLASS_MAYBE: default: g_return_if_reached (); break; } g_variant_unref (value); }
static guint json_parse_object (JsonParser *parser, JsonScanner *scanner, JsonNode **node) { JsonParserPrivate *priv = parser->priv; JsonObject *object; JsonNode *old_current; guint token; old_current = priv->current_node; priv->current_node = json_node_init_object (json_node_alloc (), NULL); object = json_object_new (); token = json_scanner_get_next_token (scanner); g_assert (token == G_TOKEN_LEFT_CURLY); g_signal_emit (parser, parser_signals[OBJECT_START], 0); while (token != G_TOKEN_RIGHT_CURLY) { guint next_token = json_scanner_peek_next_token (scanner); JsonNode *member = NULL; gchar *name; /* we need to abort here because empty objects do not * have member names */ if (next_token == G_TOKEN_RIGHT_CURLY) break; /* parse the member's name */ if (next_token != G_TOKEN_STRING) { JSON_NOTE (PARSER, "Missing object member name"); priv->error_code = JSON_PARSER_ERROR_INVALID_BAREWORD; json_object_unref (object); json_node_free (priv->current_node); priv->current_node = old_current; return G_TOKEN_STRING; } /* member name */ token = json_scanner_get_next_token (scanner); name = g_strdup (scanner->value.v_string); if (name == NULL || *name == '\0') { JSON_NOTE (PARSER, "Empty object member name"); priv->error_code = JSON_PARSER_ERROR_EMPTY_MEMBER_NAME; json_object_unref (object); json_node_free (priv->current_node); priv->current_node = old_current; return G_TOKEN_STRING; } JSON_NOTE (PARSER, "Object member '%s'", name); /* a colon separates names from values */ next_token = json_scanner_peek_next_token (scanner); if (next_token != ':') { JSON_NOTE (PARSER, "Missing object member name separator"); priv->error_code = JSON_PARSER_ERROR_MISSING_COLON; g_free (name); json_object_unref (object); json_node_free (priv->current_node); priv->current_node = old_current; return ':'; } /* we swallow the ':' */ token = json_scanner_get_next_token (scanner); g_assert (token == ':'); next_token = json_scanner_peek_next_token (scanner); /* parse the member's value */ switch (next_token) { case G_TOKEN_LEFT_BRACE: JSON_NOTE (PARSER, "Nested array at member %s", name); token = json_parse_array (parser, scanner, &member); break; case G_TOKEN_LEFT_CURLY: JSON_NOTE (PARSER, "Nested object at member %s", name); token = json_parse_object (parser, scanner, &member); break; default: /* once a member name is defined we need a value */ token = json_scanner_get_next_token (scanner); token = json_parse_value (parser, scanner, token, &member); break; } if (token != G_TOKEN_NONE || member == NULL) { /* the json_parse_* functions will have set the error code */ g_free (name); json_object_unref (object); json_node_free (priv->current_node); priv->current_node = old_current; return token; } next_token = json_scanner_peek_next_token (scanner); if (next_token == G_TOKEN_COMMA) { token = json_scanner_get_next_token (scanner); next_token = json_scanner_peek_next_token (scanner); /* look for trailing commas */ if (next_token == G_TOKEN_RIGHT_CURLY) { priv->error_code = JSON_PARSER_ERROR_TRAILING_COMMA; json_object_unref (object); json_node_free (member); json_node_free (priv->current_node); priv->current_node = old_current; return G_TOKEN_RIGHT_BRACE; } } else if (next_token == G_TOKEN_STRING) { priv->error_code = JSON_PARSER_ERROR_MISSING_COMMA; json_object_unref (object); json_node_free (member); json_node_free (priv->current_node); priv->current_node = old_current; return G_TOKEN_COMMA; } JSON_NOTE (PARSER, "Object member '%s' completed", name); json_node_set_parent (member, priv->current_node); json_object_set_member (object, name, member); g_signal_emit (parser, parser_signals[OBJECT_MEMBER], 0, object, name); g_free (name); token = next_token; } json_scanner_get_next_token (scanner); json_node_take_object (priv->current_node, object); json_node_set_parent (priv->current_node, old_current); g_signal_emit (parser, parser_signals[OBJECT_END], 0, object); if (node != NULL && *node == NULL) *node = priv->current_node; priv->current_node = old_current; return G_TOKEN_NONE; }
static guint json_parse_array (JsonParser *parser, JsonScanner *scanner, JsonNode **node) { JsonParserPrivate *priv = parser->priv; JsonNode *old_current; JsonArray *array; guint token; gint idx; old_current = priv->current_node; priv->current_node = json_node_init_array (json_node_alloc (), NULL); array = json_array_new (); token = json_scanner_get_next_token (scanner); g_assert (token == G_TOKEN_LEFT_BRACE); g_signal_emit (parser, parser_signals[ARRAY_START], 0); idx = 0; while (token != G_TOKEN_RIGHT_BRACE) { guint next_token = json_scanner_peek_next_token (scanner); JsonNode *element = NULL; /* parse the element */ switch (next_token) { case G_TOKEN_LEFT_BRACE: JSON_NOTE (PARSER, "Nested array at index %d", idx); token = json_parse_array (parser, scanner, &element); break; case G_TOKEN_LEFT_CURLY: JSON_NOTE (PARSER, "Nested object at index %d", idx); token = json_parse_object (parser, scanner, &element); break; case G_TOKEN_RIGHT_BRACE: goto array_done; default: token = json_scanner_get_next_token (scanner); token = json_parse_value (parser, scanner, token, &element); break; } if (token != G_TOKEN_NONE || element == NULL) { /* the json_parse_* functions will have set the error code */ json_array_unref (array); json_node_free (priv->current_node); priv->current_node = old_current; return token; } next_token = json_scanner_peek_next_token (scanner); if (next_token == G_TOKEN_COMMA) { token = json_scanner_get_next_token (scanner); next_token = json_scanner_peek_next_token (scanner); /* look for trailing commas */ if (next_token == G_TOKEN_RIGHT_BRACE) { priv->error_code = JSON_PARSER_ERROR_TRAILING_COMMA; json_array_unref (array); json_node_free (priv->current_node); json_node_free (element); priv->current_node = old_current; return G_TOKEN_RIGHT_BRACE; } } JSON_NOTE (PARSER, "Array element %d completed", idx + 1); json_node_set_parent (element, priv->current_node); json_array_add_element (array, element); g_signal_emit (parser, parser_signals[ARRAY_ELEMENT], 0, array, idx); token = next_token; } array_done: json_scanner_get_next_token (scanner); json_node_take_array (priv->current_node, array); json_node_set_parent (priv->current_node, old_current); g_signal_emit (parser, parser_signals[ARRAY_END], 0, array); if (node != NULL && *node == NULL) *node = priv->current_node; priv->current_node = old_current; return G_TOKEN_NONE; }
static guint json_parse_value (JsonParser *parser, JsonScanner *scanner, guint token, JsonNode **node) { JsonParserPrivate *priv = parser->priv; JsonNode *current_node = priv->current_node; gboolean is_negative = FALSE; if (token == '-') { guint next_token = json_scanner_peek_next_token (scanner); if (next_token == G_TOKEN_INT || next_token == G_TOKEN_FLOAT) { is_negative = TRUE; token = json_scanner_get_next_token (scanner); } else return G_TOKEN_INT; } switch (token) { case G_TOKEN_INT: JSON_NOTE (PARSER, "abs(node): %" G_GINT64_FORMAT " (sign: %s)", scanner->value.v_int64, is_negative ? "negative" : "positive"); *node = json_node_init_int (json_node_alloc (), is_negative ? scanner->value.v_int64 * -1 : scanner->value.v_int64); break; case G_TOKEN_FLOAT: JSON_NOTE (PARSER, "abs(node): %.6f (sign: %s)", scanner->value.v_float, is_negative ? "negative" : "positive"); *node = json_node_init_double (json_node_alloc (), is_negative ? scanner->value.v_float * -1.0 : scanner->value.v_float); break; case G_TOKEN_STRING: JSON_NOTE (PARSER, "node: '%s'", scanner->value.v_string); *node = json_node_init_string (json_node_alloc (), scanner->value.v_string); break; case JSON_TOKEN_TRUE: case JSON_TOKEN_FALSE: JSON_NOTE (PARSER, "node: '%s'", JSON_TOKEN_TRUE ? "<true>" : "<false>"); *node = json_node_init_boolean (json_node_alloc (), token == JSON_TOKEN_TRUE ? TRUE : FALSE); break; case JSON_TOKEN_NULL: JSON_NOTE (PARSER, "node: <null>"); *node = json_node_init_null (json_node_alloc ()); break; case G_TOKEN_IDENTIFIER: JSON_NOTE (PARSER, "node: identifier '%s'", scanner->value.v_identifier); priv->error_code = JSON_PARSER_ERROR_INVALID_BAREWORD; *node = NULL; return G_TOKEN_SYMBOL; default: { JsonNodeType cur_type; *node = NULL; JSON_NOTE (PARSER, "node: invalid token"); cur_type = json_node_get_node_type (current_node); if (cur_type == JSON_NODE_ARRAY) { priv->error_code = JSON_PARSER_ERROR_PARSE; return G_TOKEN_RIGHT_BRACE; } else if (cur_type == JSON_NODE_OBJECT) { priv->error_code = JSON_PARSER_ERROR_PARSE; return G_TOKEN_RIGHT_CURLY; } else { priv->error_code = JSON_PARSER_ERROR_INVALID_BAREWORD; return G_TOKEN_SYMBOL; } } break; } return G_TOKEN_NONE; }
static GVariant * parse_json_dictionary (JsonNode *node, const GVariantType *entry_type, GError **error) { const GVariantType *key_type; const GVariantType *value_type; GVariant *result = NULL; GPtrArray *children; JsonObject *object; JsonNode *key_node; GList *members = NULL; gboolean is_string; GVariant *value; GVariant *key; GVariant *child; GList *l; children = g_ptr_array_new (); if (!check_type (node, JSON_NODE_OBJECT, 0, error)) goto out; object = json_node_get_object (node); key_type = g_variant_type_key (entry_type); value_type = g_variant_type_value (entry_type); is_string = (g_variant_type_equal (key_type, G_VARIANT_TYPE_STRING) || g_variant_type_equal (key_type, G_VARIANT_TYPE_OBJECT_PATH) || g_variant_type_equal (key_type, G_VARIANT_TYPE_SIGNATURE)); members = json_object_get_members (object); for (l = members; l != NULL; l = g_list_next (l)) { if (is_string) { key_node = json_node_init_string (json_node_alloc (), l->data); } else { key_node = cockpit_json_parse (l->data, -1, NULL); if (key_node == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "Unexpected key '%s' in JSON object", (gchar *)l->data); goto out; } } key = parse_json (key_node, key_type, error); json_node_free (key_node); if (!key) goto out; value = parse_json (json_object_get_member (object, l->data), value_type, error); if (!value) { g_variant_unref (key); goto out; } child = g_variant_new_dict_entry (key, value); g_ptr_array_add (children, child); } result = g_variant_new_array (entry_type, (GVariant *const *)children->pdata, children->len); children->len = 0; out: g_list_free (members); g_ptr_array_foreach (children, (GFunc)g_variant_unref, NULL); g_ptr_array_free (children, TRUE); return result; }
int main (int argc, char *argv[]) { GOptionContext *context = NULL; /* owned */ ExitStatus retval = EXIT_SUCCESS; guint i; GPtrArray/*<owned WblSchema>*/ *schemas = NULL; /* owned */ WblSchema *meta_schema = NULL; /* owned */ WblMetaSchemaType meta_schema_type; const gchar *meta_schema_name; GError *error = NULL; #if !GLIB_CHECK_VERSION (2, 35, 0) g_type_init (); #endif setlocale (LC_ALL, ""); /* Redirect debug output to stderr so that stdout is purely useful. */ g_log_set_default_handler (wbl_log, NULL); /* Command line parsing. */ context = g_option_context_new (_("— validate JSON schemas")); g_option_context_set_summary (context, _("Validate one or more JSON Schemas, " "checking for well-formedness, and " "validating against a JSON " "meta-schema.\n\nThere are two " "meta-schemas:\n • meta-schema: Used " "for schemas written for pure " "validation.\n • hyper-meta-schema: " "Used for schemas written for " "validation and hyper-linking.\n\nThe " "hyper-meta-schema is used by default, " "and is a superset of meta-schema.\n\n" "Read about JSON Schema here: " "http://json-schema.org/.")); g_option_context_add_main_entries (context, entries, PACKAGE_NAME); if (!g_option_context_parse (context, &argc, &argv, &error)) { gchar *message; message = g_strdup_printf (_("Option parsing failed: %s"), error->message); g_printerr ("%s: %s\n", argv[0], message); g_free (message); g_clear_error (&error); retval = EXIT_INVALID_OPTIONS; goto done; } /* Load the schemas. */ schemas = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); for (i = 0; option_schema_filenames != NULL && option_schema_filenames[i] != NULL; i++) { WblSchema *schema = NULL; /* owned */ schema = wbl_schema_new (); wbl_schema_load_from_file (schema, option_schema_filenames[i], &error); /* Print error or other messages from validation. */ wbl_print_validate_messages (schema, TRUE /* use colour */); if (error != NULL) { if (!option_quiet) { gchar *message; message = g_strdup_printf (_("Invalid JSON schema ‘%s’: %s"), option_schema_filenames[i], error->message); g_printerr ("%s: %s\n", argv[0], message); g_free (message); } if (retval == EXIT_SUCCESS) { retval = EXIT_INVALID_SCHEMA; } g_clear_error (&error); if (!option_ignore_errors) { g_object_unref (schema); goto done; } else { g_object_unref (schema); continue; } } g_object_set_data (G_OBJECT (schema), "filename", option_schema_filenames[i]); g_ptr_array_add (schemas, schema); /* transfer */ } /* Choose which meta-schema to use. */ if (option_no_hyper) { meta_schema_type = WBL_META_SCHEMA_META_SCHEMA; meta_schema_name = "meta-schema"; } else { meta_schema_type = WBL_META_SCHEMA_HYPER_META_SCHEMA; meta_schema_name = "hyper-meta-schema"; } meta_schema = wbl_meta_schema_load_schema (meta_schema_type, &error); g_assert_no_error (error); /* Validate each of the JSON schemas against the meta-schema. */ for (i = 0; i < schemas->len; i++) { WblSchema *schema; /* unowned */ const gchar *schema_filename; WblSchemaNode *schema_root; /* unowned */ JsonNode *schema_root_node = NULL; /* owned */ JsonObject *schema_root_object; /* unowned */ schema = schemas->pdata[i]; schema_filename = g_object_get_data (G_OBJECT (schema), "filename"); if (!option_quiet) { gchar *message; message = g_strdup_printf (_("Validating ‘%s’ against %s…"), schema_filename, meta_schema_name); g_print ("%s ", message); g_free (message); } /* Try applying the meta-schema to the schema. */ schema_root = wbl_schema_get_root (schema); schema_root_object = wbl_schema_node_get_root (schema_root); schema_root_node = json_node_alloc (); json_node_init_object (schema_root_node, schema_root_object); wbl_schema_apply (meta_schema, schema_root_node, &error); json_node_free (schema_root_node); if (!option_quiet) { g_print ("%s", (error == NULL) ? _("OK") : _("FAIL")); g_print ("\n"); } if (error != NULL) { if (!option_quiet) { gchar *message; message = g_strdup_printf (_("Validation error for ‘%s’ against %s: %s"), schema_filename, meta_schema_name, error->message); g_printerr ("%s: %s\n", argv[0], message); g_free (message); } if (retval == EXIT_SUCCESS) { retval = EXIT_SCHEMA_VALIDATION_FAILED; } g_clear_error (&error); if (!option_ignore_errors) { goto done; } } } done: if (context != NULL) { g_option_context_free (context); } if (schemas != NULL) { g_ptr_array_unref (schemas); } g_clear_object (&meta_schema); return retval; }