--- parser3/src/classes/json.C 2024/09/13 04:01:22 1.61 +++ parser3/src/classes/json.C 2024/10/16 03:28:30 1.64 @@ -20,19 +20,24 @@ #include "pa_vxdoc.h" #endif -volatile const char * IDENT_JSON_C="$Id: json.C,v 1.61 2024/09/13 04:01:22 moko Exp $"; +volatile const char * IDENT_JSON_C="$Id: json.C,v 1.64 2024/10/16 03:28:30 moko Exp $"; // class class MJson: public Methoded { public: MJson(); + + override Value* get_element(const String&); + override const VJunction* put_element(const String&, Value*); }; // global variable DECLARE_CLASS_VAR(json, new MJson); +bool handle_array_default=true; + // methods struct Json : public PA_Allocated { Stack stack; @@ -55,7 +60,7 @@ struct Json : public PA_Allocated { Json(Charset* acharset): stack(), key_stack(), key(NULL), result(NULL), hook_object(NULL), hook_array(NULL), request(NULL), charset(acharset), taint(String::L_TAINTED), handle_double(true), handle_int(true), - handle_array(true), distinct(D_EXCEPTION){} + handle_array(handle_array_default), distinct(D_EXCEPTION){} bool set_distinct(const String &value){ if (value == "first") distinct = D_FIRST; @@ -73,6 +78,31 @@ struct Json : public PA_Allocated { } }; + +Value* MJson::get_element(const String& aname) { + if (aname=="array"){ + return new VString(*new String(handle_array_default ? "array" : "hash")); + } + return Methoded::get_element(aname); +} + +const VJunction* MJson::put_element(const String& aname, Value* avalue) { + if (aname=="array"){ + Json json(NULL); + if (avalue->get_string()){ + const String& sarray=avalue->as_string(); + if (json.set_handle_array(sarray)){ + handle_array_default=json.handle_array; + return 0; + } + throw Exception(PARSER_RUNTIME, &sarray, "$json:array must be 'array' or 'hash'"); + } + throw Exception(PARSER_RUNTIME, 0, "$json:array must be 'array' or 'hash'"); + } + return Methoded::put_element(aname, avalue); +} + + static void set_json_value(Json *json, Value *value){ VHashBase *top = json->stack.top_value(); if(json->key == NULL){ @@ -93,7 +123,7 @@ static void set_json_value(Json *json, V if (top->hash().put_dont_replace(*json->key, value)){ for(int i=2;;i++){ String key; - key << *json->key << "_" << format(i, 0); + key << *json->key << "_" << pa_uitoa(i); if (!top->hash().put_dont_replace(key, value)) break; } } @@ -378,10 +408,10 @@ static void _parse(Request& r, MethodPar if (json.result) r.write(*json.result); } -const uint ANTI_ENDLESS_JSON_STRING_RECOURSION=128; +const uint ANTI_ENDLESS_JSON_STRING_RECURSION=128; char *get_indent(uint level){ - static char* cache[ANTI_ENDLESS_JSON_STRING_RECOURSION]={}; + static char* cache[ANTI_ENDLESS_JSON_STRING_RECURSION]={}; if (!cache[level]){ char *result = static_cast(pa_malloc_atomic(level+1)); memset(result, '\t', level); @@ -392,7 +422,7 @@ char *get_indent(uint level){ } String *get_delim(uint level){ - static String* cache[ANTI_ENDLESS_JSON_STRING_RECOURSION]={}; + static String* cache[ANTI_ENDLESS_JSON_STRING_RECURSION]={}; if (!cache[level]){ char *result = static_cast(pa_malloc_atomic(level+2+1+1)); @@ -407,7 +437,7 @@ String *get_delim(uint level){ } String *get_array_delim(uint level){ - static String* cache[ANTI_ENDLESS_JSON_STRING_RECOURSION]={}; + static String* cache[ANTI_ENDLESS_JSON_STRING_RECURSION]={}; if (!cache[level]){ char *result = static_cast(pa_malloc_atomic(level+2+1)); @@ -420,16 +450,16 @@ String *get_array_delim(uint level){ return cache[level]; } -class Json_string_recoursion { +class Json_string_recursion { Json_options& foptions; public: - Json_string_recoursion(Json_options& aoptions) : foptions(aoptions) { - if(++foptions.json_string_recoursion==ANTI_ENDLESS_JSON_STRING_RECOURSION) + Json_string_recursion(Json_options& aoptions) : foptions(aoptions) { + if(++foptions.json_string_recursion==ANTI_ENDLESS_JSON_STRING_RECURSION) throw Exception(PARSER_RUNTIME, 0, "call canceled - endless json recursion detected"); } - ~Json_string_recoursion() { - if(foptions.json_string_recoursion) - foptions.json_string_recoursion--; + ~Json_string_recursion() { + if(foptions.json_string_recursion) + foptions.json_string_recursion--; } }; @@ -439,24 +469,24 @@ const String* Json_options::hash_json_st if(!hash || !hash->count()) return new String("{}", String::L_AS_IS); - Json_string_recoursion go_down(*this); + Json_string_recursion go_down(*this); String& result = *new String("{\n", String::L_AS_IS); if (indent){ String *delim=NULL; - indent=get_indent(json_string_recoursion); + indent=get_indent(json_string_recursion); for(HashStringValue::Iterator i(*hash); i; i.next() ){ if (delim){ result << *delim; } else { result << indent << "\""; - delim = get_delim(json_string_recoursion); + delim = get_delim(json_string_recursion); } result << String(i.key(), String::L_JSON) << "\":" << value_json_string(i.key(), *i.value(), *this); } - result << "\n" << (indent=get_indent(json_string_recoursion-1)) << "}"; + result << "\n" << (indent=get_indent(json_string_recursion-1)) << "}"; } else { @@ -477,24 +507,24 @@ const String* Json_options::array_json_s if(!array || !array->count()) return new String("[]", String::L_AS_IS); - Json_string_recoursion go_down(*this); + Json_string_recursion go_down(*this); String& result = *new String("[\n", String::L_AS_IS); if (indent){ String *delim=NULL; - indent=get_indent(json_string_recoursion); + indent=get_indent(json_string_recursion); for(ArrayValue::Iterator i(*array); i; i.next() ){ if (delim){ result << *delim; } else { result << indent; - delim = get_array_delim(json_string_recoursion); + delim = get_array_delim(json_string_recursion); } result << value_json_string(i.key(), i.value() ? *i.value() : *VVoid::get(), *this); } - result << "\n" << (indent=get_indent(json_string_recoursion-1)) << "]"; + result << "\n" << (indent=get_indent(json_string_recursion-1)) << "]"; } else { @@ -515,26 +545,26 @@ const String* Json_options::array_compac if(!array || !array->count()) return new String("[]", String::L_AS_IS); - Json_string_recoursion go_down(*this); + Json_string_recursion go_down(*this); String& result = *new String("[\n", String::L_AS_IS); if (indent){ String *delim=NULL; - indent=get_indent(json_string_recoursion); + indent=get_indent(json_string_recursion); for(ArrayValue::Iterator i(*array); i; i.next() ){ if (i.value()){ if (delim){ result << *delim; } else { result << indent; - delim = get_array_delim(json_string_recoursion); + delim = get_array_delim(json_string_recursion); } result << value_json_string(i.key(), *i.value(), *this); } } - result << "\n" << (indent=get_indent(json_string_recoursion-1)) << "]"; + result << "\n" << (indent=get_indent(json_string_recursion-1)) << "]"; } else { @@ -609,7 +639,7 @@ static void _string(Request& r, MethodPa } else if(key == "indent"){ if(value->is_string()){ json.indent=value->as_string().cstr(); - json.json_string_recoursion=strlen(json.indent); + json.json_string_recursion=strlen(json.indent); } else json.indent=r.process(*value).as_bool() ? "" : NULL; valid_options++; } else if(key == "table" && value->is_string()){