2012-01-24 13 views
7

Tworzę konsolę opartą na powłoce v8, wziąłem przykładowy kod, który jest oparty na v8 i działa bardzo dobrze, ale próbuję przekonwertować obiekt v8 :: do wersji łańcuchowej (json), ale nie dowiedziałem się, jak to zrobić.Używanie stringify z powłoki v8

Oto mój przykładowy kod wewnątrz shell.cc:



    v8::Handle test(const v8::Arguments& args) { 
     v8::HandleScope handle_scope; 
     const char* json; 
     v8::String::Utf8Value strJson(args[0]); 
     printf(ToCString(json)); 
     if (args[0]->IsObject()) { 
      printf("it's an object\n"); 
     } 
     return v8::String::New(""); 
    } 

Na powłoce stworzyłem test.js plików z tego:



    var a = { name: 'John' }; 
    test(a); 

i mam to po wykonaniu js wewnątrz konsola shell:



    [object Object] 
    It's an object 

Co chcę jest:



    { "name": "John" } 

przypadku zmiany kodu js do:



    var a = { name: 'John'} 
    test(JSON.stringify(a)); 

działa bardzo dobrze, ale nie chcę użytkownik mający umieć analizować zmiennej javascript do JSON, i nie chcę sprawdzać każde pojedyncze wejście na obiekcie i parsuj je ręcznie.

Czy istnieje sposób wykonywania tej samej instrukcji wewnątrz kodu shell.cc w języku C? coś takiego:



    v8::Handle<v8::String> temp = JSON.parse(arg[0]); 

aktualizacji: To jak mam obchodzenia tego, ale chcę czystszy sposób, aby zrobić to samo:



    const char* toJson(const v8::Local<v8::Object>& obj) { 
     std::stringstream ss; 
     ss << "{"; 
     v8::Local<v8::Array> propertyNames = obj->GetPropertyNames(); 

     for (int x = 0; x < propertyNames->Length(); x++) { 
      if (x != 0) { 
      ss << ", "; 
      } 
      v8::String::Utf8Value name(propertyNames->Get(x)); 
      ss << "\"" << ToCString(name) << "\":"; 
      v8::Local<v8::Value> val = obj->GetInternalField(x); 
      if (val->IsObject()) { 
       ss << toJson(val->ToObject()); 
      } else { 
       ss << "\"" << ToCString(v8::String::Utf8Value(val)) << "\""; 
      } 
     } 

     ss << "}"; 

     const char* result = ss.str().c_str(); 
     return result; 
    } 

    v8::Handle test(const v8::Arguments& args) { 
     v8::HandleScope handle_scope; 
     const char* json; 
     v8::String::Utf8Value strJson(args[0]); 
     if (args[0]->IsObject()) { 
      char* json = toJson(args[0]); 
      // ... 
      // Some operations with the json 
      // ... 
     } 
     return v8::String::New(""); 
    } 

Odpowiedz

10

Znalazłem ten sposób robi odwrotnie (do JSON obiekt v8), używając funkcji v8s wbudowanej w funkcję JSON.parse. http://www.mail-archive.com/[email protected]/msg04430.html

Regulacja ta używać JSON.stringify zamiast wyglądają trochę jak ten (niesprawdzone):

Handle<String> toJson(Handle<Value> object) 
{ 
    HandleScope scope; 

    Handle<Context> context = Context::GetCurrent(); 
    Handle<Object> global = context->Global(); 

    Handle<Object> JSON = global->Get(String::New("JSON"))->ToObject(); 
    Handle<Function> JSON_stringify = Handle<Function>::Cast(JSON->Get(String::New("stringify"))); 

    return scope.Close(JSON_stringify->Call(JSON, 1, object)); 
} 
0

chciałem unikać teraz-przestarzałe metody V8 dla własnej realizacji v8::Value -to- string nawrócenia, więc zestawiłem tę funkcję, czerpiąc inspirację z odpowiedzi Michaela. Minusem jest to, że jest bardzo szczegółowy:

bool MakeStringValue(const string& str, v8::Isolate* isolate, 
        v8::Handle<v8::Value>* out_value) { 
    const v8::MaybeLocal<v8::String> maybe_string = v8::String::NewFromUtf8(
     isolate, str.c_str(), v8::NewStringType::kNormal, str.size()); 
    v8::Handle<v8::String> value; 
    if (!maybe_string.ToLocal(&value)) { 
    return false; 
    } 
    *out_value = static_cast<v8::Handle<v8::Value>>(value); 
    return true; 
} 

bool ConvertValueToString(v8::Handle<v8::Value> value, v8::Isolate* isolate, 
          v8::Local<v8::Context> context, 
          string* value_string) { 
    v8::Local<v8::Object> global = context->Global(); 

    v8::Handle<v8::Value> json_string_value; 
    v8::Handle<v8::Value> stringify_string_value; 
    if (!MakeStringValue("JSON", isolate, &json_string_value) || 
     !MakeStringValue("stringify", isolate, &stringify_string_value)) { 
    return false; 
    } 
    const v8::MaybeLocal<v8::Value> maybe_json_value = 
     global->Get(context, json_string_value); 
    v8::Handle<v8::Value> json_value; 
    if (!maybe_json_value.ToLocal(&json_value)) { 
    return false; 
    } 

    v8::MaybeLocal<v8::Object> maybe_json_object = json_value->ToObject(context); 
    v8::Handle<v8::Object> json_object; 
    if (!maybe_json_object.ToLocal(&json_object)) { 
    return false; 
    } 

    const v8::MaybeLocal<v8::Value> maybe_stringify_value = 
     json_object->Get(context, stringify_string_value); 
    v8::Handle<v8::Value> stringify_value; 
    if (!maybe_stringify_value.ToLocal(&stringify_value)) { 
    return false; 
    } 

    v8::Function* stringify_function = v8::Function::Cast(*stringify_value); 

    v8::TryCatch try_catch(isolate); 
    const v8::MaybeLocal<v8::Value> maybe_result = 
     stringify_function->Call(context, json_object, 1, &value); 
    v8::Local<v8::Value> result; 
    if (try_catch.HasCaught() || !maybe_result.ToLocal(&result) || 
     result.IsEmpty() || result->IsNullOrUndefined() || !result->IsString()) { 
    return false; 
    } 

    v8::Local<v8::String> result_string; 
    if (!result->ToString(context).ToLocal(&result_string)) { 
    return false; 
    } 
    v8::String::Utf8Value utf8_value(result_string); 
    // operator* returns a const char*. 
    if (*utf8_value == nullptr) { 
    return false; 
    } 
    value_string->assign(*utf8_value, utf8_value.length()); 
    return true; 
}