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>
62 @brief Used internally by a JSON parser.
64 A jsonParserContext stores these values in order to remember where the parser is in the
68 #define JSON_STATE_IN_OBJECT 0x1
69 #define JSON_STATE_IN_ARRAY 0x2
70 #define JSON_STATE_IN_STRING 0x4
71 #define JSON_STATE_IN_UTF 0x8
72 #define JSON_STATE_IN_ESCAPE 0x10
73 #define JSON_STATE_IN_KEY 0x20
74 #define JSON_STATE_IN_NULL 0x40
75 #define JSON_STATE_IN_TRUE 0x80
76 #define JSON_STATE_IN_FALSE 0x100
77 #define JSON_STATE_IN_NUMBER 0x200
78 #define JSON_STATE_IS_INVALID 0x400
79 #define JSON_STATE_IS_DONE 0x800
80 #define JSON_STATE_START_COMMEN 0x1000
81 #define JSON_STATE_IN_COMMENT 0x2000
82 #define JSON_STATE_END_COMMENT 0x4000
86 @name Parser state operations
87 @ Macros to manipulate the parser state in a jsonParserContext.
91 #define JSON_STATE_SET(ctx,s) ctx->state |= s;
93 #define JSON_STATE_REMOVE(ctx,s) ctx->state &= ~s;
94 /** Check if a state is set. */
95 #define JSON_STATE_CHECK(ctx,s) (ctx->state & s) ? 1 : 0
96 /** Pop a state off the stack. */
97 #define JSON_STATE_POP(ctx) osrfListPop( ctx->stateStack );
98 /** Push a state on the stack. */
99 #define JSON_STATE_PUSH(ctx, state) osrfListPush( ctx->stateStack,(void*) state );
100 /** Check which container type we're currently in. */
101 #define JSON_STATE_PEEK(ctx) osrfListGetIndex(ctx->stateStack, ctx->stateStack->size -1)
102 /** Compare stack values. */
103 #define JSON_STATE_CHECK_STACK(ctx, s) (JSON_STATE_PEEK(ctx) == (void*) s ) ? 1 : 0
104 /** Check if a parser state is set. */
105 #define JSON_PARSE_FLAG_CHECK(ctx, f) (ctx->flags & f) ? 1 : 0
110 @brief Macros defining types of jsonObject.
112 A jsonObject includes a @em type member with one of these values, identifying the type of
113 jsonObject. Client code should treat the @em type member as read-only.
118 #define JSON_STRING 2
119 #define JSON_NUMBER 3
125 This macro is used only by a JSON parser. It probably has no business being published
128 #define JSON_PARSE_LAST_CHUNK 0x1 /* this is the last part of the string we're parsing */
131 @name JSON extensions
133 These two macros define tags used for encoding class information. @em JSON_CLASS_KEY
134 labels a class name, and @em JSON_DATA_KEY labels an associated value.
136 Because each of these macros is subject to an ifndef clause, client code may override
137 the default choice of labels by defining alternatives before including this header.
138 At this writing, this potential for customization is unused.
141 #ifndef JSON_CLASS_KEY
142 #define JSON_CLASS_KEY "__c"
144 #ifndef JSON_DATA_KEY
145 #define JSON_DATA_KEY "__p"
150 @brief Stores the current state of a JSON parser.
152 One form of JSON parser operates as a finite state machine. It stores the various
153 JSON_STATE_* values in order to keep track of what it's doing. It also maintains a
154 stack of previous states in order to keep track of nesting.
156 The internals of this struct are published in the header in order to provide the client
157 with a window into the operations of the parser. By installing its own callback functions,
158 and possibly by tinkering with the insides of the jsonParserContext, the client code can
159 customize the behavior of the parser.
161 In practice only the default callbacks are ever installed, at this writing. The potential
162 for customized parsing is unused.
164 struct jsonParserContextStruct {
165 int state; /**< What are we currently parsing. */
166 const char* chunk; /**< The chunk we're currently parsing. */
167 int index; /**< Where we are in parsing the current chunk. */
168 int chunksize; /**< Size of the current chunk. */
169 int flags; /**< Parser flags. */
170 osrfList* stateStack; /**< The nest of object/array states. */
171 growing_buffer* buffer; /**< Buffer for building strings, numbers, and keywords. */
172 growing_buffer* utfbuf; /**< Holds the current unicode characters. */
173 void* userData; /**< Opaque user pointer. We ignore this. */
174 const struct jsonParserHandlerStruct* handler; /**< The event handler struct. */
176 typedef struct jsonParserContextStruct jsonParserContext;
179 @brief A collection of function pointers for customizing parser behavior.
181 The client code can install pointers to its own functions in this struct, in order to
182 customize the behavior of the parser at various points in the parsing.
184 struct jsonParserHandlerStruct {
185 void (*handleStartObject) (void* userData);
186 void (*handleObjectKey) (void* userData, char* key);
187 void (*handleEndObject) (void* userData);
188 void (*handleStartArray) (void* userData);
189 void (*handleEndArray) (void* userData);
190 void (*handleNull) (void* userData);
191 void (*handleString) (void* userData, char* string);
192 void (*handleBool) (void* userData, int boolval);
193 void (*handleNumber) (void* userData, const char* numstr);
194 void (*handleError) (void* userData, char* err, ...);
196 typedef struct jsonParserHandlerStruct jsonParserHandler;
199 @brief Representation of a JSON string in memory
201 Different types of jsonObject use different members of the @em value union.
203 Numbers are stored as character strings, using the same buffer that we use for
204 strings. As a result, a JSON_NUMBER can store numbers that cannot be represented
207 (We used to store numbers as doubles. We still have the @em n member lying around as
208 a relic of those times, but we don't use it. We can't get rid of it yet, either. Long
211 struct _jsonObjectStruct {
212 unsigned long size; /**< Number of sub-items. */
213 char* classname; /**< Optional class hint (not part of the JSON spec). */
214 int type; /**< JSON type. */
215 struct _jsonObjectStruct* parent; /**< Whom we're attached to. */
216 /** Union used for various types of cargo. */
218 osrfHash* h; /**< Object container. */
219 osrfList* l; /**< Array container. */
220 char* s; /**< String or number. */
222 double n; /**< Number (no longer used). */
225 typedef struct _jsonObjectStruct jsonObject;
228 @brief Iterator for traversing a jsonObject.
230 A jsonIterator traverses a jsonIterator only at a single level. It does @em not descend
231 into lower levels to traverse them recursively.
233 struct _jsonIteratorStruct {
234 jsonObject* obj; /**< The object we're traversing. */
235 osrfHashIterator* hashItr; /**< The iterator for this hash. */
236 const char* key; /**< If this object is a hash, the current key. */
237 unsigned long index; /**< If this object is an array, the index. */
239 typedef struct _jsonIteratorStruct jsonIterator;
244 @brief Allocate a new parser context object.
245 @param handler Pointer to a collection of function pointers for callback functions.
246 @param userData Opaque user pointer which is available to callbacks; ignored by the parser.
247 @return An allocated parser context, or NULL on error.
249 jsonParserContext* jsonNewParser( const jsonParserHandler* handler, void* userData);
252 @brief Free a jsonParserContext.
253 @param ctx Pointer to the jsonParserContext to be freed.
255 void jsonParserFree( jsonParserContext* ctx );
258 @brief Parse a chunk of data.
259 @param ctx Pointer to the parser context.
260 @param data Pointer the data to parse.
261 @param datalen The size of the chunk to parse.
262 @param flags Reserved.
264 int jsonParseChunk( jsonParserContext* ctx, const char* data, int datalen, int flags );
267 @name Parsing functions
269 There are two sets of parsing functions, which are mostly plug-compatible with each other.
273 - jsonParseStringRaw()
274 - jsonParseStringFmt()
276 ...and a newer series:
279 - jsonParseStringRaw();
280 - jsonParseStringFmt();
282 The first series is based on a finite state machine. Its innards are accessible, in
283 theory, through the jsonParserContext structure and through callback functions. In
284 practice this flexibility is unused at this writing.
286 The second series is based on recursive descent. It doesn't use the jsonParserContext
287 structure, nor does it accept callback functions. However it is faster than the first
288 parser. In addition its syntax checking is much stricter -- it catches many kinds of
289 syntax errors that slip through the first parser.
293 @brief Parse a JSON string;
294 @param str Pointer to the JSON string to parse.
295 @return The resulting JSON object, or NULL on error.
297 jsonObject* jsonParseString( const char* str );
298 jsonObject* jsonParseStringRaw( const char* str );
299 jsonObject* jsonParseStringFmt( const char* str, ... );
302 @brief Parse a JSON string;
303 @param s Pointer to the JSON string to parse.
304 @return The resulting JSON object, or NULL on error.
306 jsonObject* jsonParse( const char* s );
307 jsonObject* jsonParseRaw( const char* s );
308 jsonObject* jsonParseFmt( const char* str, ... );
312 @brief Parses a JSON string, using a customized error handler.
313 @param errorHandler A function pointer to an error-handling function.
314 @param str The string to parse.
315 @return The resulting JSON object, or NULL on error.
317 jsonObject* jsonParseStringHandleError( void (*errorHandler) (const char*), char* str, ... );
319 jsonObject* jsonNewObject(const char* data);
321 jsonObject* jsonNewObjectFmt(const char* data, ...);
323 jsonObject* jsonNewObjectType(int type);
325 jsonObject* jsonNewNumberObject( double num );
327 jsonObject* jsonNewNumberStringObject( const char* numstr );
329 jsonObject* jsonNewBoolObject(int val);
331 void jsonObjectFree( jsonObject* o );
333 void jsonObjectFreeUnused( void );
335 unsigned long jsonObjectPush(jsonObject* o, jsonObject* newo);
337 unsigned long jsonObjectSetKey(
338 jsonObject* o, const char* key, jsonObject* newo);
341 * Turns the object into a JSON string. The string must be freed by the caller */
342 char* jsonObjectToJSON( const jsonObject* obj );
343 char* jsonObjectToJSONRaw( const jsonObject* obj );
345 jsonObject* jsonObjectGetKey( jsonObject* obj, const char* key );
347 const jsonObject* jsonObjectGetKeyConst( const jsonObject* obj, const char* key );
349 jsonIterator* jsonNewIterator(const jsonObject* obj);
351 void jsonIteratorFree(jsonIterator* itr);
353 jsonObject* jsonIteratorNext(jsonIterator* iter);
355 int jsonIteratorHasNext(const jsonIterator* itr);
357 jsonObject* jsonObjectGetIndex( const jsonObject* obj, unsigned long index );
359 unsigned long jsonObjectSetIndex(jsonObject* dest, unsigned long index, jsonObject* newObj);
361 unsigned long jsonObjectRemoveIndex(jsonObject* dest, unsigned long index);
363 jsonObject* jsonObjectExtractIndex(jsonObject* dest, unsigned long index);
365 unsigned long jsonObjectRemoveKey( jsonObject* dest, const char* key);
367 char* jsonObjectGetString(const jsonObject*);
369 double jsonObjectGetNumber( const jsonObject* obj );
371 void jsonObjectSetString(jsonObject* dest, const char* string);
373 void jsonObjectSetNumber(jsonObject* dest, double num);
375 int jsonObjectSetNumberString(jsonObject* dest, const char* string);
377 void jsonObjectSetClass(jsonObject* dest, const char* classname );
379 const char* jsonObjectGetClass(const jsonObject* dest);
381 int jsonBoolIsTrue( const jsonObject* boolObj );
383 void jsonSetBool(jsonObject* bl, int val);
385 jsonObject* jsonObjectClone( const jsonObject* o );
387 char* jsonObjectToSimpleString( const jsonObject* o );
389 char* doubleToString( double num );
391 int jsonIsNumeric( const char* s );
393 char* jsonScrubNumber( const char* s );
396 @brief Provide an XPATH style search interface to jsonObjects.
397 @param obj Pointer to the jsonObject to be searched.
398 @param path Pointer to a printf-style format string specifying the search path. Subsequent
399 parameters, if any, are formatted and inserted into the formatted string.
400 @return A copy of the object at the specified location, if it exists, or NULL if it doesn't.
402 Example search path: /some/node/here.
404 Every element in the path must be a proper object, a JSON_HASH.
406 The calling code is responsible for freeing the jsonObject to which the returned pointer
409 jsonObject* jsonObjectFindPath( const jsonObject* obj, const char* path, ... );
413 @brief Prettify a JSON string for printing, by adding newlines and other white space.
414 @param jsonString Pointer to the original JSON string.
415 @return Pointer to a prettified JSON string.
417 The calling code is responsible for freeing the returned string.
419 char* jsonFormatString( const char* jsonString );
421 /* sets the error handler for all parsers */
422 void jsonSetGlobalErrorHandler(void (*errorHandler) (const char*));
424 /* ------------------------------------------------------------------------- */
426 * The following methods provide a facility for serializing and
427 * deserializing "classed" JSON objects. To give a JSON object a
428 * class, simply call jsonObjectSetClass().
429 * Then, calling jsonObjectEncodeClass() will convert the JSON
430 * object (and any sub-objects) to a JSON object with class
431 * wrapper objects like so:
432 * { "__c" : "classname", "__p" : [json_thing] }
433 * In this example __c is the class key and __p is the data (object)
434 * key. The keys are defined by the constants
435 * JSON_CLASS_KEY and JSON_DATA_KEY
436 * To revive a serialized object, simply call
437 * jsonObjectDecodeClass()
441 /* Converts a class-wrapped object into an object with the
443 * Caller must free the returned object
445 jsonObject* jsonObjectDecodeClass( const jsonObject* obj );
448 /* Converts an object with a classname into a
449 * class-wrapped (serialized) object
450 * Caller must free the returned object
452 jsonObject* jsonObjectEncodeClass( const jsonObject* obj );
454 /* ------------------------------------------------------------------------- */
458 * Generates an XML representation of a JSON object */
459 char* jsonObjectToXML(const jsonObject*);
462 * Builds a JSON object from the provided XML
464 jsonObject* jsonXMLToJSONObject(const char* xml);