--- parser3/src/classes/json.C 2010/09/24 23:18:08 1.9 +++ parser3/src/classes/json.C 2011/05/18 01:25:06 1.14 @@ -4,7 +4,7 @@ Copyright (c) 2010 ArtLebedev Group (http://www.artlebedev.com) */ -static const char * const IDENT_RESPONSE_C="$Date: 2010/09/24 23:18:08 $"; +static const char * const IDENT_RESPONSE_C="$Date: 2011/05/18 01:25:06 $"; #include "classes.h" #include "pa_vmethod_frame.h" @@ -16,13 +16,15 @@ static const char * const IDENT_RESPONSE #include "pa_charsets.h" #include "JSON_parser.h" +#ifdef XML +#include "pa_vxdoc.h" +#endif + // class class MJson: public Methoded { public: MJson(); -public: // Methoded - bool used_directly() { return true; } }; // global variable @@ -94,7 +96,7 @@ String* json_string(Json *json, const JS static Value *json_hook(Request &r, Junction *hook, String* key, Value* value){ VMethodFrame frame(*hook->method, r.method_frame, hook->self); - Value *params[]={new VString(*key), value}; + Value *params[]={new VString(key ? *key : String::Empty), value}; frame.store_params(params, 2); r.execute_method(frame); @@ -131,12 +133,13 @@ static int json_callback(Json *json, int } case JSON_T_ARRAY_BEGIN:{ VHash *v = new VHash(); - set_json_value(json, v); + if (json->stack.count()) set_json_value(json, v); json->stack.push(v); break; } case JSON_T_ARRAY_END: - json->stack.pop(); + // libjson supports array at top level, we too + json->result = json->stack.pop(); break; case JSON_T_KEY: json->key = json_string(json, value); @@ -255,7 +258,7 @@ char *get_indent(uint level){ return cache[level]; } -const String& value_json_string(Value& v, Json_options* options); +const String& value_json_string(String::Body key, Value& v, Json_options* options); const String& hash_json_string(HashStringValue &hash, Json_options* options) { if(!hash.count()) @@ -276,7 +279,7 @@ const String& hash_json_string(HashStrin result << options->indent << "\""; delim = new String(",\n", String::L_AS_IS); *delim << options->indent << "\""; } - result << String(i.key(), String::L_JSON) << "\":" << value_json_string(*i.value(), options); + result << String(i.key(), String::L_JSON) << "\":" << value_json_string(i.key(), *i.value(), options); } result << "\n" << (options->indent=get_indent(level-1)) << "}"; @@ -285,7 +288,7 @@ const String& hash_json_string(HashStrin bool need_delim=false; for(HashStringValue::Iterator i(hash); i; i.next() ){ result << (need_delim ? ",\n\"" : "\""); - result << String(i.key(), String::L_JSON) << "\":" << value_json_string(*i.value(), options); + result << String(i.key(), String::L_JSON) << "\":" << value_json_string(i.key(), *i.value(), options); need_delim=true; } result << "\n}"; @@ -296,14 +299,14 @@ const String& hash_json_string(HashStrin return result; } -const String& value_json_string(Value& v, Json_options* options) { +const String& value_json_string(String::Body key, Value& v, Json_options* options) { if(options && options->methods) if(Value* method=options->methods->get(v.type())){ Junction* junction=method->get_junction(); VMethodFrame frame(*junction->method, options->r->method_frame, junction->self); - Value *params[]={&v, (options->params) ? options->params : VVoid::get()}; - frame.store_params(params, 2); + Value *params[]={new VString(*new String(key, String::L_JSON)), &v, (options->params) ? options->params : VVoid::get()}; + frame.store_params(params, 3); options->r->execute_method(frame); @@ -324,6 +327,7 @@ static void _string(Request& r, MethodPa json.params=params.get(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(); @@ -341,16 +345,21 @@ static void _string(Request& r, MethodPa } 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' or 'object'"); + 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' or 'text'"); valid_options++; +#ifdef XML + } else if(key == "xdoc" && (vvalue = value->get_hash())){ + json.xdoc_options=new XDocOutputOptions(r, vvalue); + valid_options++; +#endif } else if(Junction* junction=value->get_junction()){ - if(!junction->method || !junction->method->params_names || junction->method->params_names->count() != 2) - throw Exception(PARSER_RUNTIME, 0, "$.%s must be parser method with 2 parameters", key.cstr()); + if(!junction->method || !junction->method->params_names || junction->method->params_names->count() != 3) + throw Exception(PARSER_RUNTIME, 0, "$.%s must be parser method with 3 parameters", key.cstr()); methods->put(key, value); valid_options++; } @@ -361,7 +370,9 @@ static void _string(Request& r, MethodPa json.methods=methods; } - r.write_pass_lang(value_json_string(params[0], &json)); + const String& result_string=value_json_string(String::Body(), params[0], &json); + String::Body result_body=result_string.cstr_to_string_body_untaint(String::L_JSON, 0, &r.charsets); + r.write_pass_lang(*new String(result_body, String::L_AS_IS)); } // constructor