2012-01-24 2 views
7

Я создаю консоль на основе оболочки v8, я взял пример кода, который приписывает v8, и он работает очень хорошо, но я пытаюсь преобразовать v8 :: объект в строчную версию (json), но не нашел способ сделать это.Использование stringify из оболочки v8

Вот мой пример кода внутри 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(""); 
    } 

В скорлупе я создал файл test.js с этим:



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

и я получаю это после выполнения JS в консоль оболочки:



    [object Object] 
    It's an object 

Что я хочу:



    { "name": "John" } 

если изменить код JS для:



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

это работает очень хорошо, но я не хочу, чтобы пользователь того, чтобы знать, как разобрать переменная JavaScript в JSON, и я не хочу, чтобы проверить каждый вход на объект и разбор его вручную.

Есть ли способ выполнить ту же инструкцию внутри кода shell.cc в C? что-то вроде:



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

обновление: Это, как я ее обработки, но я хочу, уборщик способ сделать то же самое:



    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(""); 
    } 

ответ

10

Я нашел способ сделать обратное (JSON в v8), используя v8s, встроенный в функцию JSON.parse. http://www.mail-archive.com/[email protected]/msg04430.html

Настройка этого использовать JSON.stringify вместо будет выглядеть вроде как это (непроверенные):

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

Я хотел, чтобы избежать использования устаревших теперь методов V8 для моей собственной реализации v8::Value -До- string преобразования, поэтому я собрал эту функцию, вдохновляясь ответом Майкла. Недостатком является то, что он очень подробный:

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; 
} 
Смежные вопросы