1 /* json-reader.h - JSON cursor parser
3 * This file is part of JSON-GLib
4 * Copyright (C) 2010 Intel Corp.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
20 * Emmanuele Bassi <ebassi@linux.intel.com>
26 * @short_description: A cursor-based parser
28 * #JsonReader provides a simple, cursor-based API for parsing a JSON DOM. It
29 * is similar, in spirit, to the XML Reader API.
31 * In case of error, #JsonReader will be set in an error state; all subsequent
32 * calls will simply be ignored until a function that resets the error state is
36 * // ask for the 7th element; if the element does not exist, the
37 * // reader will be put in an error state
38 * json_reader_read_element (reader, 6);
40 * // in case of error, this will return NULL, otherwise it will
41 * // return the value of the element
42 * str = json_reader_get_string_value (value);
44 * // this function resets the error state if any was set
45 * json_reader_end_element (reader);
48 * If you want to detect the error state as soon as possible, you can use
49 * json_reader_get_error():
51 * |[<!-- language="C" -->
52 * // like the example above, but in this case we print out the
53 * // error immediately
54 * if (!json_reader_read_element (reader, 6))
56 * const GError *error = json_reader_get_error (reader);
57 * g_print ("Unable to read the element: %s", error->message);
61 * #JsonReader is available since JSON-GLib 0.12.
68 #include <glib/gi18n-lib.h>
70 #include "json-reader.h"
71 #include "json-types-private.h"
72 #include "json-debug.h"
74 #define json_reader_return_if_error_set(r) G_STMT_START { \
75 if (((JsonReader *) (r))->priv->error != NULL) \
78 #define json_reader_return_val_if_error_set(r,v) G_STMT_START { \
79 if (((JsonReader *) (r))->priv->error != NULL) \
80 return (v); } G_STMT_END
82 struct _JsonReaderPrivate
86 JsonNode *current_node;
87 JsonNode *previous_node;
89 /* Stack of member names. */
104 static GParamSpec *reader_properties[PROP_LAST] = { NULL, };
106 G_DEFINE_TYPE_WITH_PRIVATE (JsonReader, json_reader, G_TYPE_OBJECT)
108 G_DEFINE_QUARK (json-reader-error-quark, json_reader_error)
111 json_reader_finalize (GObject *gobject)
113 JsonReaderPrivate *priv = JSON_READER (gobject)->priv;
115 if (priv->root != NULL)
116 json_node_unref (priv->root);
118 if (priv->error != NULL)
119 g_clear_error (&priv->error);
121 if (priv->members != NULL)
122 g_ptr_array_unref (priv->members);
124 G_OBJECT_CLASS (json_reader_parent_class)->finalize (gobject);
128 json_reader_set_property (GObject *gobject,
136 json_reader_set_root (JSON_READER (gobject), g_value_get_boxed (value));
140 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
146 json_reader_get_property (GObject *gobject,
154 g_value_set_boxed (value, JSON_READER (gobject)->priv->root);
158 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
164 json_reader_class_init (JsonReaderClass *klass)
166 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
171 * The root of the JSON tree that the #JsonReader should read.
175 reader_properties[PROP_ROOT] =
176 g_param_spec_boxed ("root",
178 "The root of the tree to read",
182 G_PARAM_STATIC_STRINGS);
184 gobject_class->finalize = json_reader_finalize;
185 gobject_class->set_property = json_reader_set_property;
186 gobject_class->get_property = json_reader_get_property;
187 g_object_class_install_properties (gobject_class, PROP_LAST, reader_properties);
191 json_reader_init (JsonReader *self)
193 self->priv = json_reader_get_instance_private (self);
194 self->priv->members = g_ptr_array_new_with_free_func (g_free);
199 * @node: (allow-none): a #JsonNode, or %NULL
201 * Creates a new #JsonReader. You can use this object to read the contents of
202 * the JSON tree starting from @node
204 * Return value: the newly created #JsonReader. Use g_object_unref() to
205 * release the allocated resources when done
210 json_reader_new (JsonNode *node)
212 return g_object_new (JSON_TYPE_READER, "root", node, NULL);
216 * json_reader_unset_error:
217 * @reader: a #JsonReader
219 * Unsets the error state of @reader, if set
221 * Return value: TRUE if an error was set.
223 static inline gboolean
224 json_reader_unset_error (JsonReader *reader)
226 if (reader->priv->error != NULL)
228 g_clear_error (&(reader->priv->error));
235 * json_reader_set_root:
236 * @reader: a #JsonReader
237 * @root: (allow-none): a #JsonNode
239 * Sets the root #JsonNode to be read by @reader. The @reader will take
242 * If another #JsonNode is currently set as root, it will be replaced.
247 json_reader_set_root (JsonReader *reader,
250 JsonReaderPrivate *priv;
252 g_return_if_fail (JSON_IS_READER (reader));
256 if (priv->root == root)
259 if (priv->root != NULL)
261 json_node_unref (priv->root);
263 priv->current_node = NULL;
264 priv->previous_node = NULL;
269 priv->root = json_node_copy (root);
270 priv->current_node = priv->root;
271 priv->previous_node = NULL;
274 g_object_notify_by_pspec (G_OBJECT (reader), reader_properties[PROP_ROOT]);
278 * json_reader_ser_error:
279 * @reader: a #JsonReader
280 * @error_code: the #JsonReaderError code for the error
281 * @error_fmt: format string
282 * @Varargs: list of arguments for the @error_fmt string
284 * Sets the error state of @reader using the given error code
287 * Return value: %FALSE, to be used to return immediately from
288 * the caller function
292 json_reader_set_error (JsonReader *reader,
293 JsonReaderError error_code,
294 const gchar *error_fmt,
297 JsonReaderPrivate *priv = reader->priv;
301 if (priv->error != NULL)
302 g_clear_error (&priv->error);
304 va_start (args, error_fmt);
305 error_msg = g_strdup_vprintf (error_fmt, args);
308 g_set_error_literal (&priv->error, JSON_READER_ERROR,
318 * json_reader_get_error:
319 * @reader: a #JsonReader
321 * Retrieves the #GError currently set on @reader, if the #JsonReader
324 * Return value: (transfer none): the pointer to the error, or %NULL
329 json_reader_get_error (JsonReader *reader)
331 g_return_val_if_fail (JSON_IS_READER (reader), NULL);
333 return reader->priv->error;
337 * json_reader_is_array:
338 * @reader: a #JsonReader
340 * Checks whether the @reader is currently on an array
342 * Return value: %TRUE if the #JsonReader is on an array, and %FALSE
348 json_reader_is_array (JsonReader *reader)
350 g_return_val_if_fail (JSON_IS_READER (reader), FALSE);
351 json_reader_return_val_if_error_set (reader, FALSE);
353 if (reader->priv->current_node == NULL)
356 return JSON_NODE_HOLDS_ARRAY (reader->priv->current_node);
360 * json_reader_is_object:
361 * @reader: a #JsonReader
363 * Checks whether the @reader is currently on an object
365 * Return value: %TRUE if the #JsonReader is on an object, and %FALSE
371 json_reader_is_object (JsonReader *reader)
373 g_return_val_if_fail (JSON_IS_READER (reader), FALSE);
374 json_reader_return_val_if_error_set (reader, FALSE);
376 if (reader->priv->current_node == NULL)
379 return JSON_NODE_HOLDS_OBJECT (reader->priv->current_node);
383 * json_reader_is_value:
384 * @reader: a #JsonReader
386 * Checks whether the @reader is currently on a value
388 * Return value: %TRUE if the #JsonReader is on a value, and %FALSE
394 json_reader_is_value (JsonReader *reader)
396 g_return_val_if_fail (JSON_IS_READER (reader), FALSE);
397 json_reader_return_val_if_error_set (reader, FALSE);
399 if (reader->priv->current_node == NULL)
402 return JSON_NODE_HOLDS_VALUE (reader->priv->current_node) ||
403 JSON_NODE_HOLDS_NULL (reader->priv->current_node);
407 * json_reader_read_element:
408 * @reader: a #JsonReader
409 * @index_: the index of the element
411 * Advances the cursor of @reader to the element @index_ of the array
412 * or the object at the current position.
414 * You can use the json_reader_get_value* family of functions to retrieve
415 * the value of the element; for instance:
418 * json_reader_read_element (reader, 0);
419 * int_value = json_reader_get_int_value (reader);
422 * After reading the value, json_reader_end_element() should be called to
423 * reposition the cursor inside the #JsonReader, e.g.:
426 * json_reader_read_element (reader, 1);
427 * str_value = json_reader_get_string_value (reader);
428 * json_reader_end_element (reader);
430 * json_reader_read_element (reader, 2);
431 * str_value = json_reader_get_string_value (reader);
432 * json_reader_end_element (reader);
435 * If @reader is not currently on an array or an object, or if the @index_ is
436 * bigger than the size of the array or the object, the #JsonReader will be
437 * put in an error state until json_reader_end_element() is called. This means
438 * that if used conditionally, json_reader_end_element() must be called on both
442 * if (!json_reader_read_element (reader, 1))
444 * json_reader_end_element (reader);
445 * g_set_error (error, …);
449 * str_value = json_reader_get_string_value (reader);
450 * json_reader_end_element (reader);
453 * Return value: %TRUE on success, and %FALSE otherwise
458 json_reader_read_element (JsonReader *reader,
461 JsonReaderPrivate *priv;
463 g_return_val_if_fail (JSON_READER (reader), FALSE);
464 json_reader_return_val_if_error_set (reader, FALSE);
468 if (priv->current_node == NULL)
469 priv->current_node = priv->root;
471 if (!(JSON_NODE_HOLDS_ARRAY (priv->current_node) ||
472 JSON_NODE_HOLDS_OBJECT (priv->current_node)))
473 return json_reader_set_error (reader, JSON_READER_ERROR_NO_ARRAY,
474 _("The current node is of type '%s', but "
475 "an array or an object was expected."),
476 json_node_type_name (priv->current_node));
478 switch (json_node_get_node_type (priv->current_node))
480 case JSON_NODE_ARRAY:
482 JsonArray *array = json_node_get_array (priv->current_node);
484 if (index_ >= json_array_get_length (array))
485 return json_reader_set_error (reader, JSON_READER_ERROR_INVALID_INDEX,
486 _("The index '%d' is greater than the size "
487 "of the array at the current position."),
490 priv->previous_node = priv->current_node;
491 priv->current_node = json_array_get_element (array, index_);
495 case JSON_NODE_OBJECT:
497 JsonObject *object = json_node_get_object (priv->current_node);
501 if (index_ >= json_object_get_size (object))
502 return json_reader_set_error (reader, JSON_READER_ERROR_INVALID_INDEX,
503 _("The index '%d' is greater than the size "
504 "of the object at the current position."),
507 priv->previous_node = priv->current_node;
509 members = json_object_get_members (object);
510 name = g_list_nth_data (members, index_);
512 priv->current_node = json_object_get_member (object, name);
513 g_ptr_array_add (priv->members, g_strdup (name));
515 g_list_free (members);
520 g_assert_not_reached ();
528 * json_reader_end_element:
529 * @reader: a #JsonReader
531 * Moves the cursor back to the previous node after being positioned
534 * This function resets the error state of @reader, if any was set
539 json_reader_end_element (JsonReader *reader)
541 JsonReaderPrivate *priv;
544 g_return_if_fail (JSON_IS_READER (reader));
546 if (json_reader_unset_error (reader))
551 if (priv->previous_node != NULL)
552 tmp = json_node_get_parent (priv->previous_node);
556 if (json_node_get_node_type (priv->previous_node) == JSON_NODE_OBJECT)
557 g_ptr_array_remove_index (priv->members, priv->members->len - 1);
559 priv->current_node = priv->previous_node;
560 priv->previous_node = tmp;
564 * json_reader_count_elements:
565 * @reader: a #JsonReader
567 * Counts the elements of the current position, if @reader is
568 * positioned on an array
570 * Return value: the number of elements, or -1. In case of failure
571 * the #JsonReader is set in an error state
576 json_reader_count_elements (JsonReader *reader)
578 JsonReaderPrivate *priv;
580 g_return_val_if_fail (JSON_IS_READER (reader), -1);
584 if (priv->current_node == NULL)
586 json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
587 _("No node available at the current position"));
591 if (!JSON_NODE_HOLDS_ARRAY (priv->current_node))
593 json_reader_set_error (reader, JSON_READER_ERROR_NO_ARRAY,
594 _("The current position holds a '%s' and not an array"),
595 json_node_type_get_name (JSON_NODE_TYPE (priv->current_node)));
599 return json_array_get_length (json_node_get_array (priv->current_node));
603 * json_reader_read_member:
604 * @reader: a #JsonReader
605 * @member_name: the name of the member to read
607 * Advances the cursor of @reader to the @member_name of the object at the
610 * You can use the json_reader_get_value* family of functions to retrieve
611 * the value of the member; for instance:
614 * json_reader_read_member (reader, "width");
615 * width = json_reader_get_int_value (reader);
618 * After reading the value, json_reader_end_member() should be called to
619 * reposition the cursor inside the #JsonReader, e.g.:
622 * json_reader_read_member (reader, "author");
623 * author = json_reader_get_string_value (reader);
624 * json_reader_end_member (reader);
626 * json_reader_read_member (reader, "title");
627 * title = json_reader_get_string_value (reader);
628 * json_reader_end_member (reader);
631 * If @reader is not currently on an object, or if the @member_name is not
632 * defined in the object, the #JsonReader will be put in an error state until
633 * json_reader_end_member() is called. This means that if used conditionally,
634 * json_reader_end_member() must be called on both code paths:
637 * if (!json_reader_read_member (reader, "title"))
639 * json_reader_end_member (reader);
640 * g_set_error (error, …);
644 * str_value = json_reader_get_string_value (reader);
645 * json_reader_end_member (reader);
648 * Return value: %TRUE on success, and %FALSE otherwise
653 json_reader_read_member (JsonReader *reader,
654 const gchar *member_name)
656 JsonReaderPrivate *priv;
659 g_return_val_if_fail (JSON_READER (reader), FALSE);
660 g_return_val_if_fail (member_name != NULL, FALSE);
661 json_reader_return_val_if_error_set (reader, FALSE);
665 if (priv->current_node == NULL)
666 priv->current_node = priv->root;
668 if (!JSON_NODE_HOLDS_OBJECT (priv->current_node))
669 return json_reader_set_error (reader, JSON_READER_ERROR_NO_OBJECT,
670 _("The current node is of type '%s', but "
671 "an object was expected."),
672 json_node_type_name (priv->current_node));
674 object = json_node_get_object (priv->current_node);
675 if (!json_object_has_member (object, member_name))
676 return json_reader_set_error (reader, JSON_READER_ERROR_INVALID_MEMBER,
677 _("The member '%s' is not defined in the "
678 "object at the current position."),
681 priv->previous_node = priv->current_node;
682 priv->current_node = json_object_get_member (object, member_name);
683 g_ptr_array_add (priv->members, g_strdup (member_name));
689 * json_reader_end_member:
690 * @reader: a #JsonReader
692 * Moves the cursor back to the previous node after being positioned
695 * This function resets the error state of @reader, if any was set
700 json_reader_end_member (JsonReader *reader)
702 JsonReaderPrivate *priv;
705 g_return_if_fail (JSON_IS_READER (reader));
707 if (json_reader_unset_error (reader))
712 if (priv->previous_node != NULL)
713 tmp = json_node_get_parent (priv->previous_node);
717 g_ptr_array_remove_index (priv->members, priv->members->len - 1);
719 priv->current_node = priv->previous_node;
720 priv->previous_node = tmp;
724 * json_reader_list_members:
725 * @reader: a #JsonReader
727 * Retrieves a list of member names from the current position, if @reader
728 * is positioned on an object.
730 * Return value: (transfer full): a newly allocated, %NULL-terminated
731 * array of strings holding the members name. Use g_strfreev() when
737 json_reader_list_members (JsonReader *reader)
739 JsonReaderPrivate *priv;
744 g_return_val_if_fail (JSON_IS_READER (reader), NULL);
748 if (priv->current_node == NULL)
750 json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
751 _("No node available at the current position"));
755 if (!JSON_NODE_HOLDS_OBJECT (priv->current_node))
757 json_reader_set_error (reader, JSON_READER_ERROR_NO_OBJECT,
758 _("The current position holds a '%s' and not an object"),
759 json_node_type_get_name (JSON_NODE_TYPE (priv->current_node)));
763 members = json_object_get_members (json_node_get_object (priv->current_node));
767 retval = g_new (gchar*, g_list_length (members) + 1);
768 for (l = members, i = 0; l != NULL; l = l->next, i += 1)
769 retval[i] = g_strdup (l->data);
773 g_list_free (members);
779 * json_reader_count_members:
780 * @reader: a #JsonReader
782 * Counts the members of the current position, if @reader is
783 * positioned on an object
785 * Return value: the number of members, or -1. In case of failure
786 * the #JsonReader is set in an error state
791 json_reader_count_members (JsonReader *reader)
793 JsonReaderPrivate *priv;
795 g_return_val_if_fail (JSON_IS_READER (reader), -1);
799 if (priv->current_node == NULL)
801 json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
802 _("No node available at the current position"));
806 if (!JSON_NODE_HOLDS_OBJECT (priv->current_node))
808 json_reader_set_error (reader, JSON_READER_ERROR_NO_OBJECT,
809 _("The current position holds a '%s' and not an object"),
810 json_node_type_get_name (JSON_NODE_TYPE (priv->current_node)));
814 return json_object_get_size (json_node_get_object (priv->current_node));
818 * json_reader_get_value:
819 * @reader: a #JsonReader
821 * Retrieves the #JsonNode of the current position of @reader
823 * Return value: (transfer none): a #JsonNode, or %NULL. The returned node
824 * is owned by the #JsonReader and it should not be modified or freed
830 json_reader_get_value (JsonReader *reader)
834 g_return_val_if_fail (JSON_IS_READER (reader), NULL);
835 json_reader_return_val_if_error_set (reader, NULL);
837 if (reader->priv->current_node == NULL)
839 json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
840 _("No node available at the current position"));
844 node = reader->priv->current_node;
846 if (!JSON_NODE_HOLDS_VALUE (node))
848 json_reader_set_error (reader, JSON_READER_ERROR_NO_VALUE,
849 _("The current position holds a '%s' and not a value"),
850 json_node_type_get_name (JSON_NODE_TYPE (node)));
854 return reader->priv->current_node;
858 * json_reader_get_int_value:
859 * @reader: a #JsonReader
861 * Retrieves the integer value of the current position of @reader
863 * Return value: the integer value
868 json_reader_get_int_value (JsonReader *reader)
872 g_return_val_if_fail (JSON_IS_READER (reader), 0);
873 json_reader_return_val_if_error_set (reader, 0);
875 if (reader->priv->current_node == NULL)
877 json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
878 _("No node available at the current position"));
882 node = reader->priv->current_node;
884 if (!JSON_NODE_HOLDS_VALUE (node))
886 json_reader_set_error (reader, JSON_READER_ERROR_NO_VALUE,
887 _("The current position holds a '%s' and not a value"),
888 json_node_type_get_name (JSON_NODE_TYPE (node)));
892 return json_node_get_int (reader->priv->current_node);
896 * json_reader_get_double_value:
897 * @reader: a #JsonReader
899 * Retrieves the floating point value of the current position of @reader
901 * Return value: the floating point value
906 json_reader_get_double_value (JsonReader *reader)
910 g_return_val_if_fail (JSON_IS_READER (reader), 0.0);
911 json_reader_return_val_if_error_set (reader, 0.0);
913 if (reader->priv->current_node == NULL)
915 json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
916 _("No node available at the current position"));
920 node = reader->priv->current_node;
922 if (!JSON_NODE_HOLDS_VALUE (node))
924 json_reader_set_error (reader, JSON_READER_ERROR_NO_VALUE,
925 _("The current position holds a '%s' and not a value"),
926 json_node_type_get_name (JSON_NODE_TYPE (node)));
930 return json_node_get_double (reader->priv->current_node);
934 * json_reader_get_string_value:
935 * @reader: a #JsonReader
937 * Retrieves the string value of the current position of @reader
939 * Return value: the string value
944 json_reader_get_string_value (JsonReader *reader)
948 g_return_val_if_fail (JSON_IS_READER (reader), NULL);
949 json_reader_return_val_if_error_set (reader, NULL);
951 if (reader->priv->current_node == NULL)
953 json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
954 _("No node available at the current position"));
958 node = reader->priv->current_node;
960 if (!JSON_NODE_HOLDS_VALUE (node))
962 json_reader_set_error (reader, JSON_READER_ERROR_NO_VALUE,
963 _("The current position holds a '%s' and not a value"),
964 json_node_type_get_name (JSON_NODE_TYPE (node)));
968 if (json_node_get_value_type (node) != G_TYPE_STRING)
970 json_reader_set_error (reader, JSON_READER_ERROR_INVALID_TYPE,
971 _("The current position does not hold a string type"));
975 return json_node_get_string (reader->priv->current_node);
979 * json_reader_get_boolean_value:
980 * @reader: a #JsonReader
982 * Retrieves the boolean value of the current position of @reader
984 * Return value: the boolean value
989 json_reader_get_boolean_value (JsonReader *reader)
993 g_return_val_if_fail (JSON_IS_READER (reader), FALSE);
994 json_reader_return_val_if_error_set (reader, FALSE);
996 if (reader->priv->current_node == NULL)
998 json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
999 _("No node available at the current position"));
1003 node = reader->priv->current_node;
1005 if (!JSON_NODE_HOLDS_VALUE (node))
1007 json_reader_set_error (reader, JSON_READER_ERROR_NO_VALUE,
1008 _("The current position holds a '%s' and not a value"),
1009 json_node_type_get_name (JSON_NODE_TYPE (node)));
1013 return json_node_get_boolean (node);
1017 * json_reader_get_null_value:
1018 * @reader: a #JsonReader
1020 * Checks whether the value of the current position of @reader is 'null'
1022 * Return value: %TRUE if 'null' is set, and %FALSE otherwise
1027 json_reader_get_null_value (JsonReader *reader)
1029 g_return_val_if_fail (JSON_IS_READER (reader), FALSE);
1030 json_reader_return_val_if_error_set (reader, FALSE);
1032 if (reader->priv->current_node == NULL)
1034 json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
1035 _("No node available at the current position"));
1039 return JSON_NODE_HOLDS_NULL (reader->priv->current_node);
1043 * json_reader_get_member_name:
1044 * @reader: a #JsonReader
1046 * Retrieves the name of the current member.
1048 * Return value: (transfer none): the name of the member, or %NULL
1053 json_reader_get_member_name (JsonReader *reader)
1055 g_return_val_if_fail (JSON_IS_READER (reader), NULL);
1056 json_reader_return_val_if_error_set (reader, NULL);
1058 if (reader->priv->current_node == NULL)
1060 json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
1061 _("No node available at the current position"));
1065 if (reader->priv->members->len == 0)
1068 return g_ptr_array_index (reader->priv->members,
1069 reader->priv->members->len - 1);