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
39 * json_reader_read_element (reader, 6);
41 * /* in case of error, this will return NULL, otherwise it will
42 * * return the value of the element
44 * str = json_reader_get_string_value (value);
46 * /* this function resets the error state if any was set */
47 * json_reader_end_element (reader);
50 * If you want to detect the error state as soon as possible, you can use
51 * json_reader_get_error():
54 * /* like the example above, but in this case we print out the
55 * * error immediately
57 * if (!json_reader_read_element (reader, 6))
59 * const GError *error = json_reader_get_error (reader);
60 * g_print ("Unable to read the element: %s", error->message);
64 * #JsonReader is available since JSON-GLib 0.12.
73 #include <glib/gi18n-lib.h>
75 #include "json-reader.h"
77 #include "json-types-private.h"
79 #include "json-debug.h"
81 #define json_reader_return_if_error_set(r) G_STMT_START { \
82 if (((JsonReader *) (r))->priv->error != NULL) \
85 #define json_reader_return_val_if_error_set(r,v) G_STMT_START { \
86 if (((JsonReader *) (r))->priv->error != NULL) \
87 return (v); } G_STMT_END
89 struct _JsonReaderPrivate
93 JsonNode *current_node;
94 JsonNode *previous_node;
96 gchar *current_member;
110 static GParamSpec *reader_properties[PROP_LAST] = { NULL, };
112 G_DEFINE_TYPE (JsonReader, json_reader, G_TYPE_OBJECT);
115 json_reader_finalize (GObject *gobject)
117 JsonReaderPrivate *priv = JSON_READER (gobject)->priv;
119 if (priv->root != NULL)
120 json_node_free (priv->root);
122 if (priv->error != NULL)
123 g_clear_error (&priv->error);
125 g_free (priv->current_member);
127 G_OBJECT_CLASS (json_reader_parent_class)->finalize (gobject);
131 json_reader_set_property (GObject *gobject,
139 json_reader_set_root (JSON_READER (gobject), g_value_get_boxed (value));
143 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
149 json_reader_get_property (GObject *gobject,
157 g_value_set_boxed (value, JSON_READER (gobject)->priv->root);
161 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
167 json_reader_class_init (JsonReaderClass *klass)
169 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
171 g_type_class_add_private (klass, sizeof (JsonReaderPrivate));
176 * The root of the JSON tree that the #JsonReader should read.
180 reader_properties[PROP_ROOT] =
181 g_param_spec_boxed ("root",
183 "The root of the tree to read",
187 G_PARAM_STATIC_STRINGS);
189 gobject_class->finalize = json_reader_finalize;
190 gobject_class->set_property = json_reader_set_property;
191 gobject_class->get_property = json_reader_get_property;
192 g_object_class_install_properties (gobject_class, PROP_LAST, reader_properties);
196 json_reader_init (JsonReader *self)
198 self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, JSON_TYPE_READER,
203 json_reader_error_quark (void)
205 return g_quark_from_static_string ("json-reader-error");
210 * @node: (allow-none): a #JsonNode, or %NULL
212 * Creates a new #JsonReader. You can use this object to read the contents of
213 * the JSON tree starting from @node
215 * Return value: the newly created #JsonReader. Use g_object_unref() to
216 * release the allocated resources when done
221 json_reader_new (JsonNode *node)
223 return g_object_new (JSON_TYPE_READER, "root", node, NULL);
227 * json_reader_unset_error:
228 * @reader: a #JsonReader
230 * Unsets the error state of @reader, if set
233 json_reader_unset_error (JsonReader *reader)
235 if (reader->priv->error != NULL)
236 g_clear_error (&(reader->priv->error));
240 * json_reader_set_root:
241 * @reader: a #JsonReader
242 * @root: (allow-none): a #JsonNode
244 * Sets the root #JsonNode to be read by @reader. The @reader will take
247 * If another #JsonNode is currently set as root, it will be replaced.
252 json_reader_set_root (JsonReader *reader,
255 JsonReaderPrivate *priv;
257 g_return_if_fail (JSON_IS_READER (reader));
261 if (priv->root == root)
264 if (priv->root != NULL)
266 json_node_free (priv->root);
268 priv->current_node = NULL;
269 priv->previous_node = NULL;
274 priv->root = json_node_copy (root);
275 priv->current_node = priv->root;
276 priv->previous_node = NULL;
279 g_object_notify_by_pspec (G_OBJECT (reader), reader_properties[PROP_ROOT]);
283 * json_reader_ser_error:
284 * @reader: a #JsonReader
285 * @error_code: the #JsonReaderError code for the error
286 * @error_fmt: format string
287 * @Varargs: list of arguments for the @error_fmt string
289 * Sets the error state of @reader using the given error code
292 * Return value: %FALSE, to be used to return immediately from
293 * the caller function
296 json_reader_set_error (JsonReader *reader,
297 JsonReaderError error_code,
298 const gchar *error_fmt,
301 JsonReaderPrivate *priv = reader->priv;
305 if (priv->error != NULL)
306 g_clear_error (&priv->error);
308 va_start (args, error_fmt);
309 error_msg = g_strdup_vprintf (error_fmt, args);
312 g_set_error_literal (&priv->error, JSON_READER_ERROR,
322 * json_reader_get_error:
323 * @reader: a #JsonReader
325 * Retrieves the #GError currently set on @reader, if the #JsonReader
328 * Return value: (transfer none): the pointer to the error, or %NULL
333 json_reader_get_error (JsonReader *reader)
335 g_return_val_if_fail (JSON_IS_READER (reader), FALSE);
337 return reader->priv->error;
341 * json_reader_is_array:
342 * @reader: a #JsonReader
344 * Checks whether the @reader is currently on an array
346 * Return value: %TRUE if the #JsonReader is on an array, and %FALSE
352 json_reader_is_array (JsonReader *reader)
354 g_return_val_if_fail (JSON_IS_READER (reader), FALSE);
355 json_reader_return_val_if_error_set (reader, FALSE);
357 if (reader->priv->current_node == NULL)
360 return JSON_NODE_HOLDS_ARRAY (reader->priv->current_node);
364 * json_reader_is_object:
365 * @reader: a #JsonReader
367 * Checks whether the @reader is currently on an object
369 * Return value: %TRUE if the #JsonReader is on an object, and %FALSE
375 json_reader_is_object (JsonReader *reader)
377 g_return_val_if_fail (JSON_IS_READER (reader), FALSE);
378 json_reader_return_val_if_error_set (reader, FALSE);
380 if (reader->priv->current_node == NULL)
383 return JSON_NODE_HOLDS_OBJECT (reader->priv->current_node);
387 * json_reader_is_value:
388 * @reader: a #JsonReader
390 * Checks whether the @reader is currently on a value
392 * Return value: %TRUE if the #JsonReader is on a value, and %FALSE
398 json_reader_is_value (JsonReader *reader)
400 g_return_val_if_fail (JSON_IS_READER (reader), FALSE);
401 json_reader_return_val_if_error_set (reader, FALSE);
403 if (reader->priv->current_node == NULL)
406 return JSON_NODE_HOLDS_VALUE (reader->priv->current_node);
410 * json_reader_read_element:
411 * @reader: a #JsonReader
412 * @index_: the index of the element
414 * Advances the cursor of @reader to the element @index_ of the array
415 * or the object at the current position.
417 * You can use the json_reader_get_value* family of functions to retrieve
418 * the value of the element; for instance:
421 * json_reader_read_element (reader, 0);
422 * int_value = json_reader_get_int_value (reader);
425 * After reading the value, json_reader_end_element() should be called to
426 * reposition the cursor inside the #JsonReader, e.g.:
429 * json_reader_read_element (reader, 1);
430 * str_value = json_reader_get_string_value (reader);
431 * json_reader_end_element (reader);
433 * json_reader_read_element (reader, 2);
434 * str_value = json_reader_get_string_value (reader);
435 * json_reader_end_element (reader);
438 * If @reader is not currently on an array or an object, or if the @index_ is
439 * bigger than the size of the array or the object, the #JsonReader will be
440 * put in an error state until json_reader_end_element() is called.
442 * Return value: %TRUE on success, and %FALSE otherwise
447 json_reader_read_element (JsonReader *reader,
450 JsonReaderPrivate *priv;
452 g_return_val_if_fail (JSON_READER (reader), FALSE);
453 json_reader_return_val_if_error_set (reader, FALSE);
457 if (priv->current_node == NULL)
458 priv->current_node = priv->root;
460 if (!(JSON_NODE_HOLDS_ARRAY (priv->current_node) ||
461 JSON_NODE_HOLDS_OBJECT (priv->current_node)))
462 return json_reader_set_error (reader, JSON_READER_ERROR_NO_ARRAY,
463 _("The current node is of type '%s', but "
464 "an array or an object was expected."),
465 json_node_type_name (priv->current_node));
467 switch (json_node_get_node_type (priv->current_node))
469 case JSON_NODE_ARRAY:
471 JsonArray *array = json_node_get_array (priv->current_node);
473 if (index_ >= json_array_get_length (array))
474 return json_reader_set_error (reader, JSON_READER_ERROR_INVALID_INDEX,
475 _("The index '%d' is greater than the size "
476 "of the array at the current position."),
479 priv->previous_node = priv->current_node;
480 priv->current_node = json_array_get_element (array, index_);
484 case JSON_NODE_OBJECT:
486 JsonObject *object = json_node_get_object (priv->current_node);
490 if (index_ >= json_object_get_size (object))
491 return json_reader_set_error (reader, JSON_READER_ERROR_INVALID_INDEX,
492 _("The index '%d' is greater than the size "
493 "of the object at the current position."),
496 priv->previous_node = priv->current_node;
497 g_free (priv->current_member);
499 members = json_object_get_members (object);
500 name = g_list_nth_data (members, index_);
502 priv->current_node = json_object_get_member (object, name);
503 priv->current_member = g_strdup (name);
505 g_list_free (members);
510 g_assert_not_reached ();
518 * json_reader_end_element:
519 * @reader: a #JsonReader
521 * Moves the cursor back to the previous node after being positioned
524 * This function resets the error state of @reader, if any was set
529 json_reader_end_element (JsonReader *reader)
531 JsonReaderPrivate *priv;
534 g_return_if_fail (JSON_IS_READER (reader));
536 json_reader_unset_error (reader);
540 if (priv->previous_node != NULL)
541 tmp = json_node_get_parent (priv->previous_node);
545 g_free (priv->current_member);
546 priv->current_member = NULL;
548 priv->current_node = priv->previous_node;
549 priv->previous_node = tmp;
553 * json_reader_count_elements:
554 * @reader: a #JsonReader
556 * Counts the elements of the current position, if @reader is
557 * positioned on an array
559 * Return value: the number of elements, or -1. In case of failure
560 * the #JsonReader is set in an error state
565 json_reader_count_elements (JsonReader *reader)
567 JsonReaderPrivate *priv;
569 g_return_val_if_fail (JSON_IS_READER (reader), -1);
573 if (priv->current_node == NULL)
575 json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
576 _("No node available at the current position"));
580 if (!JSON_NODE_HOLDS_ARRAY (priv->current_node))
582 json_reader_set_error (reader, JSON_READER_ERROR_NO_ARRAY,
583 _("The current position holds a '%s' and not an array"),
584 json_node_type_get_name (JSON_NODE_TYPE (priv->current_node)));
588 return json_array_get_length (json_node_get_array (priv->current_node));
592 * json_reader_read_member:
593 * @reader: a #JsonReader
594 * @member_name: the name of the member to read
596 * Advances the cursor of @reader to the @member_name of the object at the
599 * You can use the json_reader_get_value* family of functions to retrieve
600 * the value of the member; for instance:
603 * json_reader_read_member (reader, "width");
604 * width = json_reader_get_int_value (reader);
607 * After reading the value, json_reader_end_member() should be called to
608 * reposition the cursor inside the #JsonReader, e.g.:
611 * json_reader_read_member (reader, "author");
612 * author = json_reader_get_string_value (reader);
613 * json_reader_end_element (reader);
615 * json_reader_read_element (reader, "title");
616 * title = json_reader_get_string_value (reader);
617 * json_reader_end_element (reader);
620 * If @reader is not currently on an object, or if the @member_name is not
621 * defined in the object, the #JsonReader will be put in an error state until
622 * json_reader_end_member() is called.
624 * Return value: %TRUE on success, and %FALSE otherwise
629 json_reader_read_member (JsonReader *reader,
630 const gchar *member_name)
632 JsonReaderPrivate *priv;
635 g_return_val_if_fail (JSON_READER (reader), FALSE);
636 g_return_val_if_fail (member_name != NULL, FALSE);
637 json_reader_return_val_if_error_set (reader, FALSE);
641 if (priv->current_node == NULL)
642 priv->current_node = priv->root;
644 if (!JSON_NODE_HOLDS_OBJECT (priv->current_node))
645 return json_reader_set_error (reader, JSON_READER_ERROR_NO_OBJECT,
646 _("The current node is of type '%s', but "
647 "an object was expected."),
648 json_node_type_name (priv->current_node));
650 object = json_node_get_object (priv->current_node);
651 if (!json_object_has_member (object, member_name))
652 return json_reader_set_error (reader, JSON_READER_ERROR_INVALID_MEMBER,
653 _("The member '%s' is not defined in the "
654 "object at the current position."),
657 g_free (priv->current_member);
659 priv->previous_node = priv->current_node;
660 priv->current_node = json_object_get_member (object, member_name);
661 priv->current_member = g_strdup (member_name);
667 * json_reader_end_member:
668 * @reader: a #JsonReader
670 * Moves the cursor back to the previous node after being positioned
673 * This function resets the error state of @reader, if any was set
678 json_reader_end_member (JsonReader *reader)
680 JsonReaderPrivate *priv;
683 g_return_if_fail (JSON_IS_READER (reader));
685 json_reader_unset_error (reader);
689 if (priv->previous_node != NULL)
690 tmp = json_node_get_parent (priv->previous_node);
694 g_free (priv->current_member);
695 priv->current_member = NULL;
697 priv->current_node = priv->previous_node;
698 priv->previous_node = tmp;
702 * json_reader_list_members:
703 * @reader: a #JsonReader
705 * Retrieves a list of member names from the current position, if @reader
706 * is positioned on an object.
708 * Return value: (transfer full): a newly allocated, %NULL-terminated
709 * array of strings holding the members name. Use g_strfreev() when
715 json_reader_list_members (JsonReader *reader)
717 JsonReaderPrivate *priv;
722 g_return_val_if_fail (JSON_IS_READER (reader), NULL);
726 if (priv->current_node == NULL)
728 json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
729 _("No node available at the current position"));
733 if (!JSON_NODE_HOLDS_OBJECT (priv->current_node))
735 json_reader_set_error (reader, JSON_READER_ERROR_NO_OBJECT,
736 _("The current position holds a '%s' and not an object"),
737 json_node_type_get_name (JSON_NODE_TYPE (priv->current_node)));
741 members = json_object_get_members (json_node_get_object (priv->current_node));
745 retval = g_new (gchar*, g_list_length (members) + 1);
746 for (l = members, i = 0; l != NULL; l = l->next, i += 1)
747 retval[i] = g_strdup (l->data);
751 g_list_free (members);
757 * json_reader_count_members:
758 * @reader: a #JsonReader
760 * Counts the members of the current position, if @reader is
761 * positioned on an object
763 * Return value: the number of members, or -1. In case of failure
764 * the #JsonReader is set in an error state
769 json_reader_count_members (JsonReader *reader)
771 JsonReaderPrivate *priv;
773 g_return_val_if_fail (JSON_IS_READER (reader), -1);
777 if (priv->current_node == NULL)
779 json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
780 _("No node available at the current position"));
784 if (!JSON_NODE_HOLDS_OBJECT (priv->current_node))
786 json_reader_set_error (reader, JSON_READER_ERROR_NO_OBJECT,
787 _("The current position holds a '%s' and not an object"),
788 json_node_type_get_name (JSON_NODE_TYPE (priv->current_node)));
792 return json_object_get_size (json_node_get_object (priv->current_node));
796 * json_reader_get_value:
797 * @reader: a #JsonReader
799 * Retrieves the #JsonNode of the current position of @reader
801 * Return value: (transfer none): a #JsonNode, or %NULL. The returned node
802 * is owned by the #JsonReader and it should not be modified or freed
808 json_reader_get_value (JsonReader *reader)
812 g_return_val_if_fail (JSON_IS_READER (reader), NULL);
813 json_reader_return_val_if_error_set (reader, NULL);
815 if (reader->priv->current_node == NULL)
817 json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
818 _("No node available at the current position"));
822 node = reader->priv->current_node;
824 if (!JSON_NODE_HOLDS_VALUE (node))
826 json_reader_set_error (reader, JSON_READER_ERROR_NO_VALUE,
827 _("The current position holds a '%s' and not a value"),
828 json_node_type_get_name (JSON_NODE_TYPE (node)));
832 return reader->priv->current_node;
836 * json_reader_get_int_value:
837 * @reader: a #JsonReader
839 * Retrieves the integer value of the current position of @reader
841 * Return value: the integer value
846 json_reader_get_int_value (JsonReader *reader)
850 g_return_val_if_fail (JSON_IS_READER (reader), 0);
851 json_reader_return_val_if_error_set (reader, 0);
853 if (reader->priv->current_node == NULL)
855 json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
856 _("No node available at the current position"));
860 node = reader->priv->current_node;
862 if (!JSON_NODE_HOLDS_VALUE (node))
864 json_reader_set_error (reader, JSON_READER_ERROR_NO_VALUE,
865 _("The current position holds a '%s' and not a value"),
866 json_node_type_get_name (JSON_NODE_TYPE (node)));
870 if (json_node_get_value_type (node) != G_TYPE_INT64)
872 json_reader_set_error (reader, JSON_READER_ERROR_INVALID_TYPE,
873 _("The current position does not hold an integer type"));
877 return json_node_get_int (reader->priv->current_node);
881 * json_reader_get_double_value:
882 * @reader: a #JsonReader
884 * Retrieves the floating point value of the current position of @reader
886 * Return value: the floating point value
891 json_reader_get_double_value (JsonReader *reader)
895 g_return_val_if_fail (JSON_IS_READER (reader), 0.0);
896 json_reader_return_val_if_error_set (reader, 0.0);
898 if (reader->priv->current_node == NULL)
900 json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
901 _("No node available at the current position"));
905 node = reader->priv->current_node;
907 if (!JSON_NODE_HOLDS_VALUE (node))
909 json_reader_set_error (reader, JSON_READER_ERROR_NO_VALUE,
910 _("The current position holds a '%s' and not a value"),
911 json_node_type_get_name (JSON_NODE_TYPE (node)));
915 if (json_node_get_value_type (node) != G_TYPE_DOUBLE)
917 json_reader_set_error (reader, JSON_READER_ERROR_INVALID_TYPE,
918 _("The current position does not hold a floating point type"));
922 return json_node_get_double (reader->priv->current_node);
926 * json_reader_get_string_value:
927 * @reader: a #JsonReader
929 * Retrieves the string value of the current position of @reader
931 * Return value: the string value
936 json_reader_get_string_value (JsonReader *reader)
940 g_return_val_if_fail (JSON_IS_READER (reader), NULL);
941 json_reader_return_val_if_error_set (reader, NULL);
943 if (reader->priv->current_node == NULL)
945 json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
946 _("No node available at the current position"));
950 node = reader->priv->current_node;
952 if (!JSON_NODE_HOLDS_VALUE (node))
954 json_reader_set_error (reader, JSON_READER_ERROR_NO_VALUE,
955 _("The current position holds a '%s' and not a value"),
956 json_node_type_get_name (JSON_NODE_TYPE (node)));
960 if (json_node_get_value_type (node) != G_TYPE_STRING)
962 json_reader_set_error (reader, JSON_READER_ERROR_INVALID_TYPE,
963 _("The current position does not hold a string type"));
967 return json_node_get_string (reader->priv->current_node);
971 * json_reader_get_boolean_value:
972 * @reader: a #JsonReader
974 * Retrieves the boolean value of the current position of @reader
976 * Return value: the boolean value
981 json_reader_get_boolean_value (JsonReader *reader)
985 g_return_val_if_fail (JSON_IS_READER (reader), FALSE);
986 json_reader_return_val_if_error_set (reader, FALSE);
988 if (reader->priv->current_node == NULL)
990 json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
991 _("No node available at the current position"));
995 node = reader->priv->current_node;
997 if (!JSON_NODE_HOLDS_VALUE (node))
999 json_reader_set_error (reader, JSON_READER_ERROR_NO_VALUE,
1000 _("The current position holds a '%s' and not a value"),
1001 json_node_type_get_name (JSON_NODE_TYPE (node)));
1005 if (json_node_get_value_type (node) != G_TYPE_BOOLEAN)
1007 json_reader_set_error (reader, JSON_READER_ERROR_INVALID_TYPE,
1008 _("The current position does not hold a boolean type"));
1012 return json_node_get_boolean (node);
1016 * json_reader_get_null_value:
1017 * @reader: a #JsonReader
1019 * Checks whether the value of the current position of @reader is 'null'
1021 * Return value: %TRUE if 'null' is set, and %FALSE otherwise
1026 json_reader_get_null_value (JsonReader *reader)
1028 g_return_val_if_fail (JSON_IS_READER (reader), FALSE);
1029 json_reader_return_val_if_error_set (reader, FALSE);
1031 if (reader->priv->current_node == NULL)
1033 json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
1034 _("No node available at the current position"));
1038 return JSON_NODE_HOLDS_NULL (reader->priv->current_node);
1042 * json_reader_get_member_name:
1043 * @reader: a #JsonReader
1045 * Retrieves the name of the current member.
1047 * Return value: (transfer none): the name of the member, or %NULL
1052 json_reader_get_member_name (JsonReader *reader)
1054 g_return_val_if_fail (JSON_IS_READER (reader), NULL);
1055 json_reader_return_val_if_error_set (reader, NULL);
1057 if (reader->priv->current_node == NULL)
1059 json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
1060 _("No node available at the current position"));
1064 return reader->priv->current_member;