2 This file is part of GNUnet
3 Copyright (C) 2014-2017 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
22 * @brief functions to parse JSON snippets
23 * @author Florian Dold
24 * @author Benedikt Mueller
25 * @author Christian Grothoff
28 #include "gnunet_json_lib.h"
32 * Navigate and parse data in a JSON tree. Tries to parse the @a root
33 * to find all of the values given in the @a spec. If one of the
34 * entries in @a spec cannot be found or parsed, the name of the JSON
35 * field is returned in @a error_json_name, and the offset of the
36 * entry in @a spec is returned in @a error_line.
38 * @param root the JSON node to start the navigation at.
39 * @param spec parse specification array
40 * @param[out] error_json_name which JSON field was problematic
41 * @param[out] which index into @a spec did we encounter an error
42 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
45 GNUNET_JSON_parse (const json_t *root,
46 struct GNUNET_JSON_Specification *spec,
47 const char **error_json_name,
48 unsigned int *error_line)
52 for (unsigned int i = 0; NULL != spec[i].parser; i++)
56 if (NULL == spec[i].field)
57 pos = (json_t *) root;
59 pos = json_object_get (root, spec[i].field);
60 if ((NULL == pos) && (spec[i].is_optional))
63 (GNUNET_OK != spec[i].parser (spec[i].cls, pos, &spec[i])))
65 if (NULL != error_json_name)
66 *error_json_name = spec[i].field;
67 if (NULL != error_line)
69 GNUNET_JSON_parse_free (spec);
73 return GNUNET_OK; /* all OK! */
78 * Set the "optional" flag for a parser specification entry.
80 * @param spec specification to modify
81 * @return spec copy of @a spec with optional bit set
83 struct GNUNET_JSON_Specification
84 GNUNET_JSON_spec_mark_optional (struct GNUNET_JSON_Specification spec)
86 struct GNUNET_JSON_Specification ret = spec;
88 ret.is_optional = GNUNET_YES;
94 * Frees all elements allocated during a #GNUNET_JSON_parse()
97 * @param spec specification of the parse operation
100 GNUNET_JSON_parse_free (struct GNUNET_JSON_Specification *spec)
102 for (unsigned int i = 0; NULL != spec[i].parser; i++)
103 if (NULL != spec[i].cleaner)
104 spec[i].cleaner (spec[i].cls, &spec[i]);
109 * Set an option with a JSON value from the command line.
110 * A pointer to this function should be passed as part of the
111 * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
114 * @param ctx command line processing context
115 * @param scls additional closure (will point to the 'json_t *')
116 * @param option name of the option
117 * @param value actual value of the option as a string.
118 * @return #GNUNET_OK if parsing the value worked
121 set_json (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
126 json_t **json = scls;
129 *json = json_loads (value, JSON_REJECT_DUPLICATES, &error);
133 _ ("Failed to parse JSON in option `%s': %s (%s)\n"),
137 return GNUNET_SYSERR;
144 * Allow user to specify a JSON input value.
146 * @param shortName short name of the option
147 * @param name long name of the option
148 * @param argumentHelp help text for the option argument
149 * @param description long help text for the option
150 * @param[out] val set to the JSON specified at the command line
152 struct GNUNET_GETOPT_CommandLineOption
153 GNUNET_JSON_getopt (char shortName,
155 const char *argumentHelp,
156 const char *description,
159 struct GNUNET_GETOPT_CommandLineOption clo = { .shortName = shortName,
161 .argumentHelp = argumentHelp,
162 .description = description,
163 .require_argument = 1,
164 .processor = &set_json,
165 .scls = (void *) json };