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;
137 jsonObject* jsonParse( const char* str );
139 jsonObject* jsonParseRaw( const char* str );
141 jsonObject* jsonParseFmt( const char* str, ... );
143 jsonObject* jsonNewObject(const char* data);
145 jsonObject* jsonNewObjectFmt(const char* data, ...);
147 jsonObject* jsonNewObjectType(int type);
149 jsonObject* jsonNewNumberObject( double num );
151 jsonObject* jsonNewNumberStringObject( const char* numstr );
153 jsonObject* jsonNewBoolObject(int val);
155 void jsonObjectFree( jsonObject* o );
157 void jsonObjectFreeUnused( void );
159 unsigned long jsonObjectPush(jsonObject* o, jsonObject* newo);
161 unsigned long jsonObjectSetKey(
162 jsonObject* o, const char* key, jsonObject* newo);
165 * Turns the object into a JSON string. The string must be freed by the caller */
166 char* jsonObjectToJSON( const jsonObject* obj );
167 char* jsonObjectToJSONRaw( const jsonObject* obj );
169 jsonObject* jsonObjectGetKey( jsonObject* obj, const char* key );
171 const jsonObject* jsonObjectGetKeyConst( const jsonObject* obj, const char* key );
173 jsonIterator* jsonNewIterator(const jsonObject* obj);
175 void jsonIteratorFree(jsonIterator* itr);
177 jsonObject* jsonIteratorNext(jsonIterator* iter);
179 int jsonIteratorHasNext(const jsonIterator* itr);
181 jsonObject* jsonObjectGetIndex( const jsonObject* obj, unsigned long index );
183 unsigned long jsonObjectSetIndex(jsonObject* dest, unsigned long index, jsonObject* newObj);
185 unsigned long jsonObjectRemoveIndex(jsonObject* dest, unsigned long index);
187 jsonObject* jsonObjectExtractIndex(jsonObject* dest, unsigned long index);
189 unsigned long jsonObjectRemoveKey( jsonObject* dest, const char* key);
191 const char* jsonObjectGetString(const jsonObject*);
193 double jsonObjectGetNumber( const jsonObject* obj );
195 void jsonObjectSetString(jsonObject* dest, const char* string);
197 void jsonObjectSetNumber(jsonObject* dest, double num);
199 int jsonObjectSetNumberString(jsonObject* dest, const char* string);
201 void jsonObjectSetClass(jsonObject* dest, const char* classname );
203 const char* jsonObjectGetClass(const jsonObject* dest);
205 int jsonBoolIsTrue( const jsonObject* boolObj );
207 void jsonSetBool(jsonObject* bl, int val);
209 jsonObject* jsonObjectClone( const jsonObject* o );
211 char* jsonObjectToSimpleString( const jsonObject* o );
213 char* doubleToString( double num );
215 int jsonIsNumeric( const char* s );
217 char* jsonScrubNumber( const char* s );
220 @brief Provide an XPATH style search interface to jsonObjects.
221 @param obj Pointer to the jsonObject to be searched.
222 @param path Pointer to a printf-style format string specifying the search path. Subsequent
223 parameters, if any, are formatted and inserted into the formatted string.
224 @return A copy of the object at the specified location, if it exists, or NULL if it doesn't.
226 Example search path: /some/node/here.
228 Every element in the path must be a proper object, a JSON_HASH.
230 The calling code is responsible for freeing the jsonObject to which the returned pointer
233 jsonObject* jsonObjectFindPath( const jsonObject* obj, const char* path, ... );
237 @brief Prettify a JSON string for printing, by adding newlines and other white space.
238 @param jsonString Pointer to the original JSON string.
239 @return Pointer to a prettified JSON string.
241 The calling code is responsible for freeing the returned string.
243 char* jsonFormatString( const char* jsonString );
245 /* ------------------------------------------------------------------------- */
247 * The following methods provide a facility for serializing and
248 * deserializing "classed" JSON objects. To give a JSON object a
249 * class, simply call jsonObjectSetClass().
250 * Then, calling jsonObjectEncodeClass() will convert the JSON
251 * object (and any sub-objects) to a JSON object with class
252 * wrapper objects like so:
253 * { "__c" : "classname", "__p" : [json_thing] }
254 * In this example __c is the class key and __p is the data (object)
255 * key. The keys are defined by the constants
256 * JSON_CLASS_KEY and JSON_DATA_KEY
257 * To revive a serialized object, simply call
258 * jsonObjectDecodeClass()
262 /* Converts a class-wrapped object into an object with the
264 * Caller must free the returned object
266 jsonObject* jsonObjectDecodeClass( const jsonObject* obj );
269 /* Converts an object with a classname into a
270 * class-wrapped (serialized) object
271 * Caller must free the returned object
273 jsonObject* jsonObjectEncodeClass( const jsonObject* obj );
275 /* ------------------------------------------------------------------------- */
279 * Generates an XML representation of a JSON object */
280 char* jsonObjectToXML(const jsonObject*);
283 * Builds a JSON object from the provided XML
285 jsonObject* jsonXMLToJSONObject(const char* xml);