Utilisation de stringify à partir du shell v8
-
13-11-2019 - |
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("");
}
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;
}