Question

Je crée une console basée sur le shell v8, j'ai pris l'exemple de code fourni avec la v8 et cela fonctionne très bien, mais j'essaie de convertir un objet v8 :: en sa version chaîne (json) mais je n'ai pas trouvé de façon de le faire.

Voici mon exemple de code dans le 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("");
    }

Au niveau du shell, j'ai créé un fichier test.js avec ceci :



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

et j'obtiens ceci après avoir exécuté le js dans la console shell :



    [object Object]
    It's an object

Ce que je veux c'est :



    { "name": "John" }

si je change le code js en :



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

cela fonctionne très bien, mais je ne veux pas que l'utilisateur sache comment analyser une variable javascript en json, et je ne veux pas vérifier chaque entrée de l'objet et l'analyser manuellement.

Existe-t-il un moyen d'exécuter la même instruction dans le code shell.cc en C ?quelque chose comme:



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

mise à jour:Voici comment je gère cela, mais je veux une façon plus propre de faire de même :



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

Était-ce utile?

La solution

J'ai trouvé cette façon de faire l'inverse (objet JSON vers v8), en utilisant les v8 intégrés JSON.parse fonction. http://www.mail-archive.com/v8-users@googlegroups.com/msg04430.html

Ajuster cela pour utiliser JSON.stringify cela ressemblerait plutôt à ceci (non testé) :

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

Autres conseils

Je voulais éviter d'utiliser des méthodes v8 désormais obsolètes pour ma propre mise en œuvre de la conversion généracodiketagcode-to-generacoDiCode, donc je mets ensemble cette fonction, en prenant l'inspiration de la réponse de Michael.L'inconvénient est que c'est très verbeux:

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

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top