2012-01-24 17 views
7

Estoy creando una consola basada en shell v8, tomé el código de ejemplo que funciona con v8 y está funcionando muy bien, pero estoy tratando de convertir un objeto v8 :: a la versión de cadena de eso (json) pero no encontré una manera de hacerlo.Usando stringify desde el shell v8

Aquí está mi código de ejemplo dentro de la 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(""); 
    } 

En la cáscara que crea un archivo con este Test.js:



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

y me sale esto después de la ejecución de los js dentro la consola de comandos:



    [object Object] 
    It's an object 

lo que quiero es:



    { "name": "John" } 

si cambio el código JS para:



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

funciona muy bien, pero no quiero que el usuario tenga que saber cómo analizar una variable javascript en JSON, y yo no quiero para comprobar si hay cada entrada en el objeto y analizarlo manualmente.

¿Hay alguna manera de ejecutar la misma instrucción dentro del código shell.cc en C? algo así como:



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

actualización: Así es como yo estoy manejando esto, pero quiero una forma más limpia de lo mismo:



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

Respuesta

10

me encontré con esta forma de hacer a la inversa (JSON para objeto v8), usando v8s incorporado en la función JSON.parse. http://www.mail-archive.com/[email protected]/msg04430.html

Ajuste esta opción para utilizar JSON.stringify vez se vería algo así como esto (no probado):

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

quería evitar el uso de métodos V8 ahora en desuso, para mi propia implementación de v8::Value -a- string conversión, así que armé esta función, inspirándome en la respuesta de Michael. Lo malo es que es muy detallado:

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; 
} 
Cuestiones relacionadas