]> git.evergreen-ils.org Git - OpenSRF.git/blob - include/opensrf/osrf_json.h
Add some macros for upward compatibility from the old JSON parser.
[OpenSRF.git] / include / opensrf / osrf_json.h
1 /*
2 Copyright (C) 2006  Georgia Public Library Service 
3 Bill Erickson <billserickson@gmail.com>
4
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.
9
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.
14 */
15
16 /**
17         @file osrf_json.h
18         @brief Header for parsing JSON structures and representing them in memory.
19
20         JSON is a format for representing hierarchical data structures as text.
21
22         A JSON string may be a quoted string, a numeric literal, or any of the keywords true, false
23         and null.
24
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 ]
27
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,
31         "profound": true }
32
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/.
36
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).
41
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.
46 */
47
48 #ifndef JSON_H
49 #define JSON_H
50
51 #include <opensrf/utils.h>
52 #include <opensrf/osrf_list.h>
53 #include <opensrf/osrf_hash.h>
54
55 #ifdef __cplusplus
56 extern "C" {
57 #endif
58
59 /**
60         @name JSON types
61         @brief Macros defining types of jsonObject.
62
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.
65 */
66 /*@{*/
67 #define JSON_HASH       0
68 #define JSON_ARRAY      1
69 #define JSON_STRING     2
70 #define JSON_NUMBER     3
71 #define JSON_NULL       4
72 #define JSON_BOOL       5
73 /*@}*/
74
75 /**
76         @name JSON extensions
77
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.
80
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.
84 */
85 /*@{*/
86 #ifndef JSON_CLASS_KEY
87 #define JSON_CLASS_KEY "__c"
88 #endif
89 #ifndef JSON_DATA_KEY
90 #define JSON_DATA_KEY "__p"
91 #endif
92 /*@}*/
93
94 /**
95         @brief Representation of a JSON string in memory
96
97         Different types of jsonObject use different members of the @em value union.
98
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
101         by native C types.
102
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
105         story.)
106 */
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. */
113         union _jsonValue {
114                 osrfHash*       h;      /**< Object container. */
115                 osrfList*       l;      /**< Array container. */
116                 char*           s;      /**< String or number. */
117                 int             b;      /**< Bool. */
118                 double  n;          /**< Number (no longer used). */
119         } value;
120 };
121 typedef struct _jsonObjectStruct jsonObject;
122
123 /**
124         @brief Iterator for traversing a jsonObject.
125
126         A jsonIterator traverses a jsonIterator only at a single level.  It does @em not descend
127         into lower levels to traverse them recursively.
128 */
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. */
134 };
135 typedef struct _jsonIteratorStruct jsonIterator;
136
137 /**
138         @brief Macros for upward compatibility with an old, defunct version
139     of the JSON parser.
140 */
141 /*@{*/
142 #define jsonParseString                jsonParse
143 #define jsonParseStringRaw             jsonParseRaw
144 #define jsonParseStringFmt             jsonParseFmt
145 /*@}*/
146
147 jsonObject* jsonParse( const char* str );
148
149 jsonObject* jsonParseRaw( const char* str );
150
151 jsonObject* jsonParseFmt( const char* str, ... );
152
153 jsonObject* jsonNewObject(const char* data);
154
155 jsonObject* jsonNewObjectFmt(const char* data, ...);
156
157 jsonObject* jsonNewObjectType(int type);
158
159 jsonObject* jsonNewNumberObject( double num );
160
161 jsonObject* jsonNewNumberStringObject( const char* numstr );
162
163 jsonObject* jsonNewBoolObject(int val);
164
165 void jsonObjectFree( jsonObject* o );
166
167 void jsonObjectFreeUnused( void );
168
169 unsigned long jsonObjectPush(jsonObject* o, jsonObject* newo);
170
171 unsigned long jsonObjectSetKey(
172                 jsonObject* o, const char* key, jsonObject* newo);
173
174 /*
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 );
178
179 jsonObject* jsonObjectGetKey( jsonObject* obj, const char* key );
180
181 const jsonObject* jsonObjectGetKeyConst( const jsonObject* obj, const char* key );
182
183 jsonIterator* jsonNewIterator(const jsonObject* obj);
184
185 void jsonIteratorFree(jsonIterator* itr);
186
187 jsonObject* jsonIteratorNext(jsonIterator* iter);
188
189 int jsonIteratorHasNext(const jsonIterator* itr);
190
191 jsonObject* jsonObjectGetIndex( const jsonObject* obj, unsigned long index );
192
193 unsigned long jsonObjectSetIndex(jsonObject* dest, unsigned long index, jsonObject* newObj);
194
195 unsigned long jsonObjectRemoveIndex(jsonObject* dest, unsigned long index);
196
197 jsonObject* jsonObjectExtractIndex(jsonObject* dest, unsigned long index);
198
199 unsigned long jsonObjectRemoveKey( jsonObject* dest, const char* key);
200
201 const char* jsonObjectGetString(const jsonObject*);
202
203 double jsonObjectGetNumber( const jsonObject* obj );
204
205 void jsonObjectSetString(jsonObject* dest, const char* string);
206
207 void jsonObjectSetNumber(jsonObject* dest, double num);
208
209 int jsonObjectSetNumberString(jsonObject* dest, const char* string);
210
211 void jsonObjectSetClass(jsonObject* dest, const char* classname );
212
213 const char* jsonObjectGetClass(const jsonObject* dest);
214
215 int jsonBoolIsTrue( const jsonObject* boolObj );
216
217 void jsonSetBool(jsonObject* bl, int val);
218
219 jsonObject* jsonObjectClone( const jsonObject* o );
220
221 char* jsonObjectToSimpleString( const jsonObject* o );
222
223 char* doubleToString( double num );
224
225 int jsonIsNumeric( const char* s );
226
227 char* jsonScrubNumber( const char* s );
228
229 /**
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.
235
236         Example search path: /some/node/here.
237         
238         Every element in the path must be a proper object, a JSON_HASH.
239
240         The calling code is responsible for freeing the jsonObject to which the returned pointer
241         points.
242 */
243 jsonObject* jsonObjectFindPath( const jsonObject* obj, const char* path, ... );
244
245
246 /**
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.
250
251         The calling code is responsible for freeing the returned string.
252 */
253 char* jsonFormatString( const char* jsonString );
254
255 /* ------------------------------------------------------------------------- */
256 /*
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()
269  */
270
271
272 /* Converts a class-wrapped object into an object with the
273  * classname set
274  * Caller must free the returned object 
275  */ 
276 jsonObject* jsonObjectDecodeClass( const jsonObject* obj );
277
278
279 /* Converts an object with a classname into a
280  * class-wrapped (serialized) object
281  * Caller must free the returned object 
282  */ 
283 jsonObject* jsonObjectEncodeClass( const jsonObject* obj );
284
285 /* ------------------------------------------------------------------------- */
286
287
288 /*
289  *      Generates an XML representation of a JSON object */
290 char* jsonObjectToXML(const jsonObject*);
291
292 /*
293  * Builds a JSON object from the provided XML 
294  */
295 jsonObject* jsonXMLToJSONObject(const char* xml);
296
297 #ifdef __cplusplus
298 }
299 #endif
300
301 #endif