--- a/ucx/cx/json.h Sun Feb 16 17:38:07 2025 +0100 +++ b/ucx/cx/json.h Tue Feb 25 21:12:11 2025 +0100 @@ -26,11 +26,11 @@ * POSSIBILITY OF SUCH DAMAGE. */ /** - * \file json.h - * \brief Interface for parsing data from JSON files. - * \author Mike Becker - * \author Olaf Wintermann - * \copyright 2-Clause BSD License + * @file json.h + * @brief Interface for parsing data from JSON files. + * @author Mike Becker + * @author Olaf Wintermann + * @copyright 2-Clause BSD License */ #ifndef UCX_JSON_H @@ -146,15 +146,15 @@ */ enum cx_json_literal { /** - * The \c null literal. + * The @c null literal. */ CX_JSON_NULL, /** - * The \c true literal. + * The @c true literal. */ CX_JSON_TRUE, /** - * The \c false literal. + * The @c false literal. */ CX_JSON_FALSE }; @@ -264,7 +264,7 @@ /** * The type of this value. * - * Specifies how the \c value union shall be resolved. + * Specifies how the @c value union shall be resolved. */ CxJsonValueType type; /** @@ -309,7 +309,7 @@ */ CxJsonTokenType tokentype; /** - * True, iff the \c content must be passed to cx_strfree(). + * True, if the @c content must be passed to cx_strfree(). */ bool allocated; /** @@ -374,11 +374,6 @@ * Internally reserved memory for the value buffer stack. */ CxJsonValue* vbuf_internal[8]; - - /** - * Used internally. - */ - bool tokenizer_escape; // TODO: check if it can be replaced with look-behind }; /** @@ -403,7 +398,7 @@ * Not used as a status and never returned by any function. * * You can use this enumerator to check for all "good" status results - * by checking if the status is less than \c CX_JSON_OK. + * by checking if the status is less than @c CX_JSON_OK. * * A "good" status means, that you can refill data and continue parsing. */ @@ -449,6 +444,8 @@ bool sort_members; /** * The maximum number of fractional digits in a number value. + * The default value is 6 and values larger than 15 are reduced to 15. + * Note, that the actual number of digits may be lower, depending on the concrete number. */ uint8_t frac_max_digits; /** @@ -457,10 +454,14 @@ */ bool indent_space; /** - * If \c indent_space is true, this is the number of spaces per tab. + * If @c indent_space is true, this is the number of spaces per tab. * Indentation is only used in pretty output. */ uint8_t indent; + /** + * Set true to enable escaping of the slash character (solidus). + */ + bool escape_slash; }; /** @@ -474,6 +475,7 @@ * @return new JSON writer settings */ cx_attr_nodiscard +cx_attr_export CxJsonWriter cxJsonWriterCompact(void); /** @@ -483,17 +485,17 @@ * @return new JSON writer settings */ cx_attr_nodiscard +cx_attr_export CxJsonWriter cxJsonWriterPretty(bool use_spaces); /** * Writes a JSON value to a buffer or stream. * - * This function blocks until all data is written or an error when trying - * to write data occurs. + * This function blocks until either all data is written, or an error occurs. * The write operation is not atomic in the sense that it might happen * that the data is only partially written when an error occurs with no * way to indicate how much data was written. - * To avoid this problem, you can use a CxBuffer as \p target which is + * To avoid this problem, you can use a CxBuffer as @p target which is * unlikely to fail a write operation and either use the buffer's flush * feature to relay the data or use the data in the buffer manually to * write it to the actual target. @@ -501,10 +503,12 @@ * @param target the buffer or stream where to write to * @param value the value that shall be written * @param wfunc the write function to use - * @param settings formatting settings (or \c NULL to use a compact default) - * @return zero on success, non-zero when no or not all data could be written + * @param settings formatting settings (or @c NULL to use a compact default) + * @retval zero success + * @retval non-zero when no or not all data could be written */ cx_attr_nonnull_arg(1, 2, 3) +cx_attr_export int cxJsonWrite( void* target, const CxJsonValue* value, @@ -520,6 +524,7 @@ * @see cxJsonDestroy() */ cx_attr_nonnull_arg(1) +cx_attr_export void cxJsonInit(CxJson *json, const CxAllocator *allocator); /** @@ -529,6 +534,7 @@ * @see cxJsonInit() */ cx_attr_nonnull +cx_attr_export void cxJsonDestroy(CxJson *json); /** @@ -560,11 +566,13 @@ * @param json the json interface * @param buf the source buffer * @param len the length of the source buffer - * @return zero on success, non-zero on internal allocation error + * @retval zero success + * @retval non-zero internal allocation error * @see cxJsonFill() */ cx_attr_nonnull cx_attr_access_r(2, 3) +cx_attr_export int cxJsonFilln(CxJson *json, const char *buf, size_t len); #ifdef __cplusplus @@ -600,7 +608,7 @@ /** * Fills the input buffer. * - * @remark The JSON interface tries to avoid copying the input data. + * The JSON interface tries to avoid copying the input data. * When you use this function and cxJsonNext() interleaving, * no copies are performed. However, you must not free the * pointer to the data in that case. When you invoke the fill @@ -609,8 +617,9 @@ * an allocation of a new buffer and copying the previous contents. * * @param json the json interface - * @param buf the source string - * @return zero on success, non-zero on internal allocation error + * @param str the source string + * @retval zero success + * @retval non-zero internal allocation error * @see cxJsonFilln() */ #define cxJsonFill(json, str) _Generic((str), \ @@ -659,18 +668,24 @@ * Creates a new (empty) JSON object. * * @param allocator the allocator to use - * @return the new JSON object or \c NULL if allocation fails + * @return the new JSON object or @c NULL if allocation fails + * @see cxJsonObjPutObj() + * @see cxJsonArrAddValues() */ cx_attr_nodiscard +cx_attr_export CxJsonValue* cxJsonCreateObj(const CxAllocator* allocator); /** * Creates a new (empty) JSON array. * * @param allocator the allocator to use - * @return the new JSON array or \c NULL if allocation fails + * @return the new JSON array or @c NULL if allocation fails + * @see cxJsonObjPutArr() + * @see cxJsonArrAddValues() */ cx_attr_nodiscard +cx_attr_export CxJsonValue* cxJsonCreateArr(const CxAllocator* allocator); /** @@ -678,11 +693,12 @@ * * @param allocator the allocator to use * @param num the numeric value - * @return the new JSON value or \c NULL if allocation fails + * @return the new JSON value or @c NULL if allocation fails * @see cxJsonObjPutNumber() * @see cxJsonArrAddNumbers() */ cx_attr_nodiscard +cx_attr_export CxJsonValue* cxJsonCreateNumber(const CxAllocator* allocator, double num); /** @@ -690,11 +706,12 @@ * * @param allocator the allocator to use * @param num the numeric value - * @return the new JSON value or \c NULL if allocation fails + * @return the new JSON value or @c NULL if allocation fails * @see cxJsonObjPutInteger() * @see cxJsonArrAddIntegers() */ cx_attr_nodiscard +cx_attr_export CxJsonValue* cxJsonCreateInteger(const CxAllocator* allocator, int64_t num); /** @@ -702,14 +719,15 @@ * * @param allocator the allocator to use * @param str the string data - * @return the new JSON value or \c NULL if allocation fails - * @see cxJsonCreateCxString() + * @return the new JSON value or @c NULL if allocation fails + * @see cxJsonCreateString() * @see cxJsonObjPutString() * @see cxJsonArrAddStrings() */ cx_attr_nodiscard cx_attr_nonnull_arg(2) cx_attr_cstr_arg(2) +cx_attr_export CxJsonValue* cxJsonCreateString(const CxAllocator* allocator, const char *str); /** @@ -717,12 +735,13 @@ * * @param allocator the allocator to use * @param str the string data - * @return the new JSON value or \c NULL if allocation fails - * @see cxJsonCreateString() + * @return the new JSON value or @c NULL if allocation fails + * @see cxJsonCreateCxString() * @see cxJsonObjPutCxString() * @see cxJsonArrAddCxStrings() */ cx_attr_nodiscard +cx_attr_export CxJsonValue* cxJsonCreateCxString(const CxAllocator* allocator, cxstring str); /** @@ -730,11 +749,12 @@ * * @param allocator the allocator to use * @param lit the type of literal - * @return the new JSON value or \c NULL if allocation fails + * @return the new JSON value or @c NULL if allocation fails * @see cxJsonObjPutLiteral() * @see cxJsonArrAddLiterals() */ cx_attr_nodiscard +cx_attr_export CxJsonValue* cxJsonCreateLiteral(const CxAllocator* allocator, CxJsonLiteral lit); /** @@ -743,10 +763,12 @@ * @param arr the JSON array * @param num the array of values * @param count the number of elements - * @return zero on success, non-zero on allocation failure + * @retval zero success + * @retval non-zero allocation failure */ cx_attr_nonnull cx_attr_access_r(2, 3) +cx_attr_export int cxJsonArrAddNumbers(CxJsonValue* arr, const double* num, size_t count); /** @@ -755,10 +777,12 @@ * @param arr the JSON array * @param num the array of values * @param count the number of elements - * @return zero on success, non-zero on allocation failure + * @retval zero success + * @retval non-zero allocation failure */ cx_attr_nonnull cx_attr_access_r(2, 3) +cx_attr_export int cxJsonArrAddIntegers(CxJsonValue* arr, const int64_t* num, size_t count); /** @@ -769,11 +793,13 @@ * @param arr the JSON array * @param str the array of strings * @param count the number of elements - * @return zero on success, non-zero on allocation failure + * @retval zero success + * @retval non-zero allocation failure * @see cxJsonArrAddCxStrings() */ cx_attr_nonnull cx_attr_access_r(2, 3) +cx_attr_export int cxJsonArrAddStrings(CxJsonValue* arr, const char* const* str, size_t count); /** @@ -784,11 +810,13 @@ * @param arr the JSON array * @param str the array of strings * @param count the number of elements - * @return zero on success, non-zero on allocation failure + * @retval zero success + * @retval non-zero allocation failure * @see cxJsonArrAddStrings() */ cx_attr_nonnull cx_attr_access_r(2, 3) +cx_attr_export int cxJsonArrAddCxStrings(CxJsonValue* arr, const cxstring* str, size_t count); /** @@ -797,25 +825,29 @@ * @param arr the JSON array * @param lit the array of literal types * @param count the number of elements - * @return zero on success, non-zero on allocation failure + * @retval zero success + * @retval non-zero allocation failure */ cx_attr_nonnull cx_attr_access_r(2, 3) +cx_attr_export int cxJsonArrAddLiterals(CxJsonValue* arr, const CxJsonLiteral* lit, size_t count); /** * Add arbitrary values to a JSON array. * - * \note In contrast to all other add functions, this function adds the values + * @attention In contrast to all other add functions, this function adds the values * directly to the array instead of copying them. * * @param arr the JSON array * @param val the values * @param count the number of elements - * @return zero on success, non-zero on allocation failure + * @retval zero success + * @retval non-zero allocation failure */ cx_attr_nonnull cx_attr_access_r(2, 3) +cx_attr_export int cxJsonArrAddValues(CxJsonValue* arr, CxJsonValue* const* val, size_t count); /** @@ -823,15 +855,17 @@ * * The value will be directly added and not copied. * - * \note If a value with the specified \p name already exists, + * @note If a value with the specified @p name already exists, * it will be (recursively) freed with its own allocator. * * @param obj the JSON object * @param name the name of the value * @param child the value - * @return zero on success, non-zero on allocation failure + * @retval zero success + * @retval non-zero allocation failure */ cx_attr_nonnull +cx_attr_export int cxJsonObjPut(CxJsonValue* obj, cxstring name, CxJsonValue* child); /** @@ -839,11 +873,12 @@ * * @param obj the target JSON object * @param name the name of the new value - * @return the new value or \c NULL if allocation fails + * @return the new value or @c NULL if allocation fails * @see cxJsonObjPut() * @see cxJsonCreateObj() */ cx_attr_nonnull +cx_attr_export CxJsonValue* cxJsonObjPutObj(CxJsonValue* obj, cxstring name); /** @@ -851,11 +886,12 @@ * * @param obj the target JSON object * @param name the name of the new value - * @return the new value or \c NULL if allocation fails + * @return the new value or @c NULL if allocation fails * @see cxJsonObjPut() * @see cxJsonCreateArr() */ cx_attr_nonnull +cx_attr_export CxJsonValue* cxJsonObjPutArr(CxJsonValue* obj, cxstring name); /** @@ -864,11 +900,12 @@ * @param obj the target JSON object * @param name the name of the new value * @param num the numeric value - * @return the new value or \c NULL if allocation fails + * @return the new value or @c NULL if allocation fails * @see cxJsonObjPut() * @see cxJsonCreateNumber() */ cx_attr_nonnull +cx_attr_export CxJsonValue* cxJsonObjPutNumber(CxJsonValue* obj, cxstring name, double num); /** @@ -877,11 +914,12 @@ * @param obj the target JSON object * @param name the name of the new value * @param num the numeric value - * @return the new value or \c NULL if allocation fails + * @return the new value or @c NULL if allocation fails * @see cxJsonObjPut() * @see cxJsonCreateInteger() */ cx_attr_nonnull +cx_attr_export CxJsonValue* cxJsonObjPutInteger(CxJsonValue* obj, cxstring name, int64_t num); /** @@ -892,12 +930,13 @@ * @param obj the target JSON object * @param name the name of the new value * @param str the string data - * @return the new value or \c NULL if allocation fails + * @return the new value or @c NULL if allocation fails * @see cxJsonObjPut() * @see cxJsonCreateString() */ cx_attr_nonnull cx_attr_cstr_arg(3) +cx_attr_export CxJsonValue* cxJsonObjPutString(CxJsonValue* obj, cxstring name, const char* str); /** @@ -908,11 +947,12 @@ * @param obj the target JSON object * @param name the name of the new value * @param str the string data - * @return the new value or \c NULL if allocation fails + * @return the new value or @c NULL if allocation fails * @see cxJsonObjPut() * @see cxJsonCreateCxString() */ cx_attr_nonnull +cx_attr_export CxJsonValue* cxJsonObjPutCxString(CxJsonValue* obj, cxstring name, cxstring str); /** @@ -921,17 +961,18 @@ * @param obj the target JSON object * @param name the name of the new value * @param lit the type of literal - * @return the new value or \c NULL if allocation fails + * @return the new value or @c NULL if allocation fails * @see cxJsonObjPut() * @see cxJsonCreateLiteral() */ cx_attr_nonnull +cx_attr_export CxJsonValue* cxJsonObjPutLiteral(CxJsonValue* obj, cxstring name, CxJsonLiteral lit); /** * Recursively deallocates the memory of a JSON value. * - * \remark The type of each deallocated value will be changed + * @remark The type of each deallocated value will be changed * to #CX_JSON_NOTHING and values of such type will be skipped * by the de-allocation. That means, this function protects * you from double-frees when you are accidentally freeing @@ -939,25 +980,42 @@ * * @param value the value */ +cx_attr_export void cxJsonValueFree(CxJsonValue *value); /** * Tries to obtain the next JSON value. * + * Before this function can be called, the input buffer needs + * to be filled with cxJsonFill(). + * + * When this function returns #CX_JSON_INCOMPLETE_DATA, you can + * add the missing data with another invocation of cxJsonFill() + * and then repeat the call to cxJsonNext(). * * @param json the json interface * @param value a pointer where the next value shall be stored - * @return a status code + * @retval CX_JSON_NO_ERROR successfully retrieve the @p value + * @retval CX_JSON_NO_DATA there is no (more) data in the buffer to read from + * @retval CX_JSON_INCOMPLETE_DATA an incomplete value was read + * and more data needs to be filled + * @retval CX_JSON_NULL_DATA the buffer was never initialized + * @retval CX_JSON_BUFFER_ALLOC_FAILED allocating internal buffer space failed + * @retval CX_JSON_VALUE_ALLOC_FAILED allocating memory for a CxJsonValue failed + * @retval CX_JSON_FORMAT_ERROR_NUMBER the JSON text contains an illegally formatted number + * @retval CX_JSON_FORMAT_ERROR_UNEXPECTED_TOKEN JSON syntax error */ cx_attr_nonnull cx_attr_access_w(2) +cx_attr_export CxJsonStatus cxJsonNext(CxJson *json, CxJsonValue **value); /** * Checks if the specified value is a JSON object. * * @param value a pointer to the value - * @return true if the value is a JSON object, false otherwise + * @retval true the value is a JSON object + * @retval false otherwise */ cx_attr_nonnull static inline bool cxJsonIsObject(const CxJsonValue *value) { @@ -968,7 +1026,8 @@ * Checks if the specified value is a JSON array. * * @param value a pointer to the value - * @return true if the value is a JSON array, false otherwise + * @retval true the value is a JSON array + * @retval false otherwise */ cx_attr_nonnull static inline bool cxJsonIsArray(const CxJsonValue *value) { @@ -979,7 +1038,8 @@ * Checks if the specified value is a string. * * @param value a pointer to the value - * @return true if the value is a string, false otherwise + * @retval true the value is a string + * @retval false otherwise */ cx_attr_nonnull static inline bool cxJsonIsString(const CxJsonValue *value) { @@ -993,7 +1053,8 @@ * integer numbers. * * @param value a pointer to the value - * @return true if the value is a JSON number, false otherwise + * @retval true the value is a JSON number + * @retval false otherwise * @see cxJsonIsInteger() */ cx_attr_nonnull @@ -1005,7 +1066,8 @@ * Checks if the specified value is an integer number. * * @param value a pointer to the value - * @return true if the value is an integer number, false otherwise + * @retval true the value is an integer number + * @retval false otherwise * @see cxJsonIsNumber() */ cx_attr_nonnull @@ -1016,10 +1078,11 @@ /** * Checks if the specified value is a JSON literal. * - * JSON literals are \c true, \c false, and \c null. + * JSON literals are @c true, @c false, and @c null. * * @param value a pointer to the value - * @return true if the value is a JSON literal, false otherwise + * @retval true the value is a JSON literal + * @retval false otherwise * @see cxJsonIsTrue() * @see cxJsonIsFalse() * @see cxJsonIsNull() @@ -1033,7 +1096,8 @@ * Checks if the specified value is a Boolean literal. * * @param value a pointer to the value - * @return true if the value is either \c true or \c false, false otherwise + * @retval true the value is either @c true or @c false + * @retval false otherwise * @see cxJsonIsTrue() * @see cxJsonIsFalse() */ @@ -1043,13 +1107,14 @@ } /** - * Checks if the specified value is \c true. + * Checks if the specified value is @c true. * - * \remark Be advised, that this is not the same as - * testing \c !cxJsonIsFalse(v). + * @remark Be advised, that this is not the same as + * testing @c !cxJsonIsFalse(v). * * @param value a pointer to the value - * @return true if the value is \c true, false otherwise + * @retval true the value is @c true + * @retval false otherwise * @see cxJsonIsBool() * @see cxJsonIsFalse() */ @@ -1059,13 +1124,14 @@ } /** - * Checks if the specified value is \c false. + * Checks if the specified value is @c false. * - * \remark Be advised, that this is not the same as - * testing \c !cxJsonIsTrue(v). + * @remark Be advised, that this is not the same as + * testing @c !cxJsonIsTrue(v). * * @param value a pointer to the value - * @return true if the value is \c false, false otherwise + * @retval true the value is @c false + * @retval false otherwise * @see cxJsonIsBool() * @see cxJsonIsTrue() */ @@ -1075,10 +1141,11 @@ } /** - * Checks if the specified value is \c null. + * Checks if the specified value is @c null. * * @param value a pointer to the value - * @return true if the value is \c null, false otherwise + * @retval true the value is @c null + * @retval false otherwise * @see cxJsonIsLiteral() */ cx_attr_nonnull @@ -1089,7 +1156,7 @@ /** * Obtains a C string from the given JSON value. * - * If the \p value is not a string, the behavior is undefined. + * If the @p value is not a string, the behavior is undefined. * * @param value the JSON value * @return the value represented as C string @@ -1104,7 +1171,7 @@ /** * Obtains a UCX string from the given JSON value. * - * If the \p value is not a string, the behavior is undefined. + * If the @p value is not a string, the behavior is undefined. * * @param value the JSON value * @return the value represented as UCX string @@ -1118,7 +1185,7 @@ /** * Obtains a mutable UCX string from the given JSON value. * - * If the \p value is not a string, the behavior is undefined. + * If the @p value is not a string, the behavior is undefined. * * @param value the JSON value * @return the value represented as mutable UCX string @@ -1132,7 +1199,7 @@ /** * Obtains a double-precision floating point value from the given JSON value. * - * If the \p value is not a JSON number, the behavior is undefined. + * If the @p value is not a JSON number, the behavior is undefined. * * @param value the JSON value * @return the value represented as double @@ -1150,7 +1217,7 @@ /** * Obtains a 64-bit signed integer from the given JSON value. * - * If the \p value is not a JSON number, the behavior is undefined. + * If the @p value is not a JSON number, the behavior is undefined. * If it is a JSON number, but not an integer, the value will be * converted to an integer, possibly losing precision. * @@ -1171,8 +1238,8 @@ /** * Obtains a Boolean value from the given JSON value. * - * If the \p value is not a JSON literal, the behavior is undefined. - * The \c null literal is interpreted as \c false. + * If the @p value is not a JSON literal, the behavior is undefined. + * The @c null literal is interpreted as @c false. * * @param value the JSON value * @return the value represented as double @@ -1186,7 +1253,7 @@ /** * Returns the size of a JSON array. * - * If the \p value is not a JSON array, the behavior is undefined. + * If the @p value is not a JSON array, the behavior is undefined. * * @param value the JSON value * @return the size of the array @@ -1200,11 +1267,11 @@ /** * Returns an element from a JSON array. * - * If the \p value is not a JSON array, the behavior is undefined. + * If the @p value is not a JSON array, the behavior is undefined. * * This function guarantees to return a value. If the index is * out of bounds, the returned value will be of type - * #CX_JSON_NOTHING, but never \c NULL. + * #CX_JSON_NOTHING, but never @c NULL. * * @param value the JSON value * @param index the index in the array @@ -1213,14 +1280,15 @@ */ cx_attr_nonnull cx_attr_returns_nonnull +cx_attr_export CxJsonValue *cxJsonArrGet(const CxJsonValue *value, size_t index); /** * Returns an iterator over the JSON array elements. * - * The iterator yields values of type \c CxJsonValue* . + * The iterator yields values of type @c CxJsonValue* . * - * If the \p value is not a JSON array, the behavior is undefined. + * If the @p value is not a JSON array, the behavior is undefined. * * @param value the JSON value * @return an iterator over the array elements @@ -1228,15 +1296,16 @@ */ cx_attr_nonnull cx_attr_nodiscard +cx_attr_export CxIterator cxJsonArrIter(const CxJsonValue *value); /** * Returns an iterator over the JSON object members. * - * The iterator yields values of type \c CxJsonObjValue* which + * The iterator yields values of type @c CxJsonObjValue* which * contain the name and value of the member. * - * If the \p value is not a JSON object, the behavior is undefined. + * If the @p value is not a JSON object, the behavior is undefined. * * @param value the JSON value * @return an iterator over the object members @@ -1244,6 +1313,7 @@ */ cx_attr_nonnull cx_attr_nodiscard +cx_attr_export CxIterator cxJsonObjIter(const CxJsonValue *value); /** @@ -1251,20 +1321,21 @@ */ cx_attr_nonnull cx_attr_returns_nonnull +cx_attr_export CxJsonValue *cx_json_obj_get_cxstr(const CxJsonValue *value, cxstring name); #ifdef __cplusplus } // extern "C" -CxJsonValue *cxJsonObjGet(const CxJsonValue *value, cxstring name) { +static inline CxJsonValue *cxJsonObjGet(const CxJsonValue *value, cxstring name) { return cx_json_obj_get_cxstr(value, name); } -CxJsonValue *cxJsonObjGet(const CxJsonValue *value, cxmutstr name) { +static inline CxJsonValue *cxJsonObjGet(const CxJsonValue *value, cxmutstr name) { return cx_json_obj_get_cxstr(value, cx_strcast(name)); } -CxJsonValue *cxJsonObjGet(const CxJsonValue *value, const char *name) { +static inline CxJsonValue *cxJsonObjGet(const CxJsonValue *value, const char *name) { return cx_json_obj_get_cxstr(value, cx_str(name)); } @@ -1273,11 +1344,11 @@ /** * Returns a value corresponding to a key in a JSON object. * - * If the \p value is not a JSON object, the behavior is undefined. + * If the @p value is not a JSON object, the behavior is undefined. * * This function guarantees to return a JSON value. If the - * object does not contain \p name, the returned JSON value - * will be of type #CX_JSON_NOTHING, but never \c NULL. + * object does not contain @p name, the returned JSON value + * will be of type #CX_JSON_NOTHING, but never @c NULL. * * @param value the JSON object * @param name the key to look up