]> git.evergreen-ils.org Git - OpenSRF.git/blob - include/opensrf/osrf_json.h
Eliminate the old JSON parser, implemented in osrf_json_parser.c and
[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 jsonObject* jsonParse( const char* str );
138
139 jsonObject* jsonParseRaw( const char* str );
140
141 jsonObject* jsonParseFmt( const char* str, ... );
142
143 jsonObject* jsonNewObject(const char* data);
144
145 jsonObject* jsonNewObjectFmt(const char* data, ...);
146
147 jsonObject* jsonNewObjectType(int type);
148
149 jsonObject* jsonNewNumberObject( double num );
150
151 jsonObject* jsonNewNumberStringObject( const char* numstr );
152
153 jsonObject* jsonNewBoolObject(int val);
154
155 void jsonObjectFree( jsonObject* o );
156
157 void jsonObjectFreeUnused( void );
158
159 unsigned long jsonObjectPush(jsonObject* o, jsonObject* newo);
160
161 unsigned long jsonObjectSetKey(
162                 jsonObject* o, const char* key, jsonObject* newo);
163
164 /*
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 );
168
169 jsonObject* jsonObjectGetKey( jsonObject* obj, const char* key );
170
171 const jsonObject* jsonObjectGetKeyConst( const jsonObject* obj, const char* key );
172
173 jsonIterator* jsonNewIterator(const jsonObject* obj);
174
175 void jsonIteratorFree(jsonIterator* itr);
176
177 jsonObject* jsonIteratorNext(jsonIterator* iter);
178
179 int jsonIteratorHasNext(const jsonIterator* itr);
180
181 jsonObject* jsonObjectGetIndex( const jsonObject* obj, unsigned long index );
182
183 unsigned long jsonObjectSetIndex(jsonObject* dest, unsigned long index, jsonObject* newObj);
184
185 unsigned long jsonObjectRemoveIndex(jsonObject* dest, unsigned long index);
186
187 jsonObject* jsonObjectExtractIndex(jsonObject* dest, unsigned long index);
188
189 unsigned long jsonObjectRemoveKey( jsonObject* dest, const char* key);
190
191 const char* jsonObjectGetString(const jsonObject*);
192
193 double jsonObjectGetNumber( const jsonObject* obj );
194
195 void jsonObjectSetString(jsonObject* dest, const char* string);
196
197 void jsonObjectSetNumber(jsonObject* dest, double num);
198
199 int jsonObjectSetNumberString(jsonObject* dest, const char* string);
200
201 void jsonObjectSetClass(jsonObject* dest, const char* classname );
202
203 const char* jsonObjectGetClass(const jsonObject* dest);
204
205 int jsonBoolIsTrue( const jsonObject* boolObj );
206
207 void jsonSetBool(jsonObject* bl, int val);
208
209 jsonObject* jsonObjectClone( const jsonObject* o );
210
211 char* jsonObjectToSimpleString( const jsonObject* o );
212
213 char* doubleToString( double num );
214
215 int jsonIsNumeric( const char* s );
216
217 char* jsonScrubNumber( const char* s );
218
219 /**
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.
225
226         Example search path: /some/node/here.
227         
228         Every element in the path must be a proper object, a JSON_HASH.
229
230         The calling code is responsible for freeing the jsonObject to which the returned pointer
231         points.
232 */
233 jsonObject* jsonObjectFindPath( const jsonObject* obj, const char* path, ... );
234
235
236 /**
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.
240
241         The calling code is responsible for freeing the returned string.
242 */
243 char* jsonFormatString( const char* jsonString );
244
245 /* ------------------------------------------------------------------------- */
246 /*
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()
259  */
260
261
262 /* Converts a class-wrapped object into an object with the
263  * classname set
264  * Caller must free the returned object 
265  */ 
266 jsonObject* jsonObjectDecodeClass( const jsonObject* obj );
267
268
269 /* Converts an object with a classname into a
270  * class-wrapped (serialized) object
271  * Caller must free the returned object 
272  */ 
273 jsonObject* jsonObjectEncodeClass( const jsonObject* obj );
274
275 /* ------------------------------------------------------------------------- */
276
277
278 /*
279  *      Generates an XML representation of a JSON object */
280 char* jsonObjectToXML(const jsonObject*);
281
282 /*
283  * Builds a JSON object from the provided XML 
284  */
285 jsonObject* jsonXMLToJSONObject(const char* xml);
286
287 #ifdef __cplusplus
288 }
289 #endif
290
291 #endif