--- parser3/src/classes/json.C 2024/10/20 14:30:14 1.65 +++ parser3/src/classes/json.C 2025/10/05 19:41:27 1.68 @@ -1,7 +1,7 @@ /** @file Parser: @b json parser class. - Copyright (c) 2000-2023 Art. Lebedev Studio (http://www.artlebedev.com) + Copyright (c) 2000-2024 Art. Lebedev Studio (http://www.artlebedev.com) Authors: Konstantin Morshnev */ @@ -20,7 +20,7 @@ #include "pa_vxdoc.h" #endif -volatile const char * IDENT_JSON_C="$Id: json.C,v 1.65 2024/10/20 14:30:14 moko Exp $"; +volatile const char * IDENT_JSON_C="$Id: json.C,v 1.68 2025/10/05 19:41:27 moko Exp $"; // class @@ -522,7 +522,7 @@ const String* Json_options::array_json_s result << indent; delim = get_array_delim(json_string_recursion); } - result << value_json_string(i.key(), i.value() ? *i.value() : static_cast(*VVoid::get()), *this); + result << value_json_string(String::Body::uitoa(i.index()), i.value() ? *i.value() : static_cast(*VVoid::get()), *this); } result << "\n" << (indent=get_indent(json_string_recursion-1)) << "]"; @@ -531,7 +531,7 @@ const String* Json_options::array_json_s bool need_delim=false; for(ArrayValue::Iterator i(*array); i; i.next() ){ if(need_delim) result << ",\n"; - result << value_json_string(i.key(), i.value() ? *i.value() : static_cast(*VVoid::get()), *this); + result << value_json_string(String::Body::uitoa(i.index()), i.value() ? *i.value() : static_cast(*VVoid::get()), *this); need_delim=true; } result << "\n]"; @@ -561,7 +561,7 @@ const String* Json_options::array_compac result << indent; delim = get_array_delim(json_string_recursion); } - result << value_json_string(i.key(), *i.value(), *this); + result << value_json_string(String::Body::uitoa(i.index()), *i.value(), *this); } } result << "\n" << (indent=get_indent(json_string_recursion-1)) << "]"; @@ -572,7 +572,7 @@ const String* Json_options::array_compac for(ArrayValue::Iterator i(*array); i; i.next() ){ if (i.value()){ if(need_delim) result << ",\n"; - result << value_json_string(i.key(), *i.value(), *this); + result << value_json_string(String::Body::uitoa(i.index()), *i.value(), *this); need_delim=true; } } @@ -595,9 +595,10 @@ const String& value_json_string(String:: options.methods->put(v.type(), method ? method : VVoid::get()); } if(method && !method->is_void()) { + static const String::Body sindent("indent"); Junction* junction=method->get_junction(); HashStringValue* params_hash=options.params && options.indent ? options.params->get_hash() : NULL; - Temp_hash_value indent(params_hash, "indent", new VString(*new String(options.indent, String::L_AS_IS))); + Temp_hash_value indent(params_hash, sindent, new VString(*new String(options.indent, String::L_AS_IS))); Value *params[]={new VString(*new String(key, String::L_JSON)), &v, options.params ? options.params : VVoid::get()}; @@ -620,65 +621,52 @@ static void _string(Request& r, MethodPa if(HashStringValue* options=params.as_hash(1)) { json.params=¶ms[1]; HashStringValue* methods=new HashStringValue(); - int valid_options=0; HashStringValue* vvalue; for(HashStringValue::Iterator i(*options); i; i.next() ){ String::Body key=i.key(); Value* value=i.value(); if(key == "skip-unknown"){ json.skip_unknown=r.process(*value).as_bool(); - valid_options++; } else if(key == "one-line"){ json.one_line=r.process(*value).as_bool(); - valid_options++; } else if(key == "date" && value->is_string()){ const String& svalue=value->as_string(); if(!json.set_date_format(svalue)) throw Exception(PARSER_RUNTIME, &svalue, "must be 'sql-string', 'gmt-string', 'iso-string' or 'unix-timestamp'"); - valid_options++; } else if(key == "indent"){ if(value->is_string()){ json.indent=value->as_string().cstr(); 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()){ const String& svalue=value->as_string(); if(!json.set_table_format(svalue)) throw Exception(PARSER_RUNTIME, &svalue, "must be 'array', 'object' or 'compact'"); - valid_options++; } else if(key == "array" && value->is_string()){ const String& svalue=value->as_string(); if(!json.set_array_format(svalue)) throw Exception(PARSER_RUNTIME, &svalue, "must be 'array', 'object' or 'compact'"); - valid_options++; } else if(key == "file" && value->is_string()){ const String& svalue=value->as_string(); if(!json.set_file_format(svalue)) throw Exception(PARSER_RUNTIME, &svalue, "must be 'base64', 'text' or 'stat'"); - valid_options++; } else if(key == "void" && value->is_string()){ const String& svalue=value->as_string(); if(!json.set_void_format(svalue)) throw Exception(PARSER_RUNTIME, &svalue, "must be 'string' or 'null'"); - valid_options++; #ifdef XML } else if(key == "xdoc" && (vvalue = value->get_hash())){ json.xdoc_options=new XDocOutputOptions(); json.xdoc_options->append(r, vvalue); - valid_options++; #endif } else if(Junction* junction=value->get_junction()){ if(!junction->method || !junction->method->params_names || junction->method->params_count != 3) throw Exception(PARSER_RUNTIME, 0, "$.%s must be parser method with 3 parameters", key.cstr()); methods->put(key, value); - valid_options++; - } + } else + throw Exception(PARSER_RUNTIME, 0, CALLED_WITH_INVALID_OPTION); } - if(valid_options!=options->count()) - throw Exception(PARSER_RUNTIME, 0, CALLED_WITH_INVALID_OPTION); - // special handling for $._default if(VHashBase* vhash=dynamic_cast(¶ms[1])) if(Value* value=vhash->get_default()) { @@ -701,7 +689,7 @@ static void _string(Request& r, MethodPa for(char *c=result;*c;c++) if(*c=='\n') *c=' '; - result_body=result; + result_body=String::Body(result); } r.write(*new String(result_body, String::L_AS_IS)); }