2 Copyright (C) 2006 Georgia Public Library Service
3 Bill Erickson <billserickson@gmail.com>
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
18 @brief Header for parsing JSON structures and representing them in memory.
20 JSON is a format for representing hierarchical data structures as text.
22 A JSON string may be a quoted string, a numeric literal, or any of the keywords true, false
25 A JSON string may also be an array, i.e. a series of values, separated by commas and enclosed
26 in square brackets. For example: [ "Adams", 42, null, true ]
28 A JSON string may also be an object, i.e. a series of name/value pairs, separated by commas
29 and enclosed by curly braces. Each name/value pair is a quoted string, followed by a colon,
30 followed by a value. For example: { "Author":"Adams", "answer":42, "question":null,
33 The values in a JSON array or object may themselves be arrays or objects, nested to any
34 depth, in a hierarchical structure of arbitrary complexity. For more information about
35 JSON, see http://json.org/.
37 Like a JSON string, a jsonObject can take several different forms. It can hold a string, a
38 number, a boolean, or a null. It can also hold an array, implemented internally by an
39 osrfList (see osrf_list.h). It can also hold a series of name/value pairs, implemented
40 internally by an osrfHash (see osrf_hash.h).
42 A jsonObject can also tag its contents with a class name, typically referring to a
43 database table or view. Such an object can be translated into a JSON string where the
44 class is encoded as the value of a name/value pair, with the original jsonObject encoded
45 as the value of a second name/value pair.
51 #include <opensrf/utils.h>
52 #include <opensrf/osrf_list.h>
53 #include <opensrf/osrf_hash.h>
61 @brief Macros defining types of jsonObject.
63 A jsonObject includes a @em type member with one of these values, identifying the type of
64 jsonObject. Client code should treat the @em type member as read-only.
78 These two macros define tags used for encoding class information. @em JSON_CLASS_KEY
79 labels a class name, and @em JSON_DATA_KEY labels an associated value.
81 Because each of these macros is subject to an ifndef clause, client code may override
82 the default choice of labels by defining alternatives before including this header.
83 At this writing, this potential for customization is unused.
86 #ifndef JSON_CLASS_KEY
87 #define JSON_CLASS_KEY "__c"
90 #define JSON_DATA_KEY "__p"
95 @brief Representation of a JSON string in memory
97 Different types of jsonObject use different members of the @em value union.
99 Numbers are stored as character strings, using the same buffer that we use for
100 strings. As a result, a JSON_NUMBER can store numbers that cannot be represented
103 (We used to store numbers as doubles. We still have the @em n member lying around as
104 a relic of those times, but we don't use it. We can't get rid of it yet, either. Long
107 struct _jsonObjectStruct {
108 unsigned long size; /**< Number of sub-items. */
109 char* classname; /**< Optional class hint (not part of the JSON spec). */
110 int type; /**< JSON type. */
111 struct _jsonObjectStruct* parent; /**< Whom we're attached to. */
112 /** Union used for various types of cargo. */
114 osrfHash* h; /**< Object container. */
115 osrfList* l; /**< Array container. */
116 char* s; /**< String or number. */
118 double n; /**< Number (no longer used). */
121 typedef struct _jsonObjectStruct jsonObject;
124 @brief Iterator for traversing a jsonObject.
126 A jsonIterator traverses a jsonIterator only at a single level. It does @em not descend
127 into lower levels to traverse them recursively.
129 struct _jsonIteratorStruct {
130 jsonObject* obj; /**< The object we're traversing. */
131 osrfHashIterator* hashItr; /**< The iterator for this hash. */
132 const char* key; /**< If this object is a hash, the current key. */
133 unsigned long index; /**< If this object is an array, the index. */
135 typedef struct _jsonIteratorStruct jsonIterator;
138 @brief Macros for upward compatibility with an old, defunct version
142 #define jsonParseString jsonParse
143 #define jsonParseStringRaw jsonParseRaw
144 #define jsonParseStringFmt jsonParseFmt
147 jsonObject* jsonParse( const char* str );
149 jsonObject* jsonParseRaw( const char* str );
151 jsonObject* jsonParseFmt( const char* str, ... );
153 jsonObject* jsonNewObject(const char* data);
155 jsonObject* jsonNewObjectFmt(const char* data, ...);
157 jsonObject* jsonNewObjectType(int type);
159 jsonObject* jsonNewNumberObject( double num );
161 jsonObject* jsonNewNumberStringObject( const char* numstr );
163 jsonObject* jsonNewBoolObject(int val);
165 void jsonObjectFree( jsonObject* o );
167 void jsonObjectFreeUnused( void );
169 unsigned long jsonObjectPush(jsonObject* o, jsonObject* newo);
171 unsigned long jsonObjectSetKey(
172 jsonObject* o, const char* key, jsonObject* newo);
175 * Turns the object into a JSON string. The string must be freed by the caller */
176 char* jsonObjectToJSON( const jsonObject* obj );
177 char* jsonObjectToJSONRaw( const jsonObject* obj );
179 jsonObject* jsonObjectGetKey( jsonObject* obj, const char* key );
181 const jsonObject* jsonObjectGetKeyConst( const jsonObject* obj, const char* key );
183 jsonIterator* jsonNewIterator(const jsonObject* obj);
185 void jsonIteratorFree(jsonIterator* itr);
187 jsonObject* jsonIteratorNext(jsonIterator* iter);
189 int jsonIteratorHasNext(const jsonIterator* itr);
191 jsonObject* jsonObjectGetIndex( const jsonObject* obj, unsigned long index );
193 unsigned long jsonObjectSetIndex(jsonObject* dest, unsigned long index, jsonObject* newObj);
195 unsigned long jsonObjectRemoveIndex(jsonObject* dest, unsigned long index);
197 jsonObject* jsonObjectExtractIndex(jsonObject* dest, unsigned long index);
199 unsigned long jsonObjectRemoveKey( jsonObject* dest, const char* key);
201 const char* jsonObjectGetString(const jsonObject*);
203 double jsonObjectGetNumber( const jsonObject* obj );
205 void jsonObjectSetString(jsonObject* dest, const char* string);
207 void jsonObjectSetNumber(jsonObject* dest, double num);
209 int jsonObjectSetNumberString(jsonObject* dest, const char* string);
211 void jsonObjectSetClass(jsonObject* dest, const char* classname );
213 const char* jsonObjectGetClass(const jsonObject* dest);
215 int jsonBoolIsTrue( const jsonObject* boolObj );
217 void jsonSetBool(jsonObject* bl, int val);
219 jsonObject* jsonObjectClone( const jsonObject* o );
221 char* jsonObjectToSimpleString( const jsonObject* o );
223 char* doubleToString( double num );
225 int jsonIsNumeric( const char* s );
227 char* jsonScrubNumber( const char* s );
230 @brief Provide an XPATH style search interface to jsonObjects.
231 @param obj Pointer to the jsonObject to be searched.
232 @param path Pointer to a printf-style format string specifying the search path. Subsequent
233 parameters, if any, are formatted and inserted into the formatted string.
234 @return A copy of the object at the specified location, if it exists, or NULL if it doesn't.
236 Example search path: /some/node/here.
238 Every element in the path must be a proper object, a JSON_HASH.
240 The calling code is responsible for freeing the jsonObject to which the returned pointer
243 jsonObject* jsonObjectFindPath( const jsonObject* obj, const char* path, ... );
247 @brief Prettify a JSON string for printing, by adding newlines and other white space.
248 @param jsonString Pointer to the original JSON string.
249 @return Pointer to a prettified JSON string.
251 The calling code is responsible for freeing the returned string.
253 char* jsonFormatString( const char* jsonString );
255 /* ------------------------------------------------------------------------- */
257 * The following methods provide a facility for serializing and
258 * deserializing "classed" JSON objects. To give a JSON object a
259 * class, simply call jsonObjectSetClass().
260 * Then, calling jsonObjectEncodeClass() will convert the JSON
261 * object (and any sub-objects) to a JSON object with class
262 * wrapper objects like so:
263 * { "__c" : "classname", "__p" : [json_thing] }
264 * In this example __c is the class key and __p is the data (object)
265 * key. The keys are defined by the constants
266 * JSON_CLASS_KEY and JSON_DATA_KEY
267 * To revive a serialized object, simply call
268 * jsonObjectDecodeClass()
272 /* Converts a class-wrapped object into an object with the
274 * Caller must free the returned object
276 jsonObject* jsonObjectDecodeClass( const jsonObject* obj );
279 /* Converts an object with a classname into a
280 * class-wrapped (serialized) object
281 * Caller must free the returned object
283 jsonObject* jsonObjectEncodeClass( const jsonObject* obj );
285 /* ------------------------------------------------------------------------- */
289 * Generates an XML representation of a JSON object */
290 char* jsonObjectToXML(const jsonObject*);
293 * Builds a JSON object from the provided XML
295 jsonObject* jsonXMLToJSONObject(const char* xml);