I'm writing node.js bindings and I want to generate JSON string from v8::Object instances. I want to do it in C++. Since node.js already has JSON.stringify, I would like to use it. But I don't know how to access it from the C++ code.
2 Answers
You need to grab a reference to the global object, and then grab the stringify method;
Local<Object> obj = ... // Thing to stringify
// Get the global object.
// Same as using 'global' in Node
Local<Object> global = Context::GetCurrent()->Global();
// Get JSON
// Same as using 'global.JSON'
Local<Object> JSON = Local<Object>::Cast(
global->Get(String::New("JSON")));
// Get stringify
// Same as using 'global.JSON.stringify'
Local<Function> stringify = Local<Function>::Cast(
JSON->Get(String::New("stringify")));
// Stringify the object
// Same as using 'global.JSON.stringify.apply(global.JSON, [ obj ])
Local<Value> args[] = { obj };
Local<String> result = Local<String>::Cast(stringify->Call(JSON, 1, args));
1 Comment
stav
Some things have apparently changed in the V8 API: 1. There is no
GetCurrent and usually you get the global from the isolate using isolate->GetCurrentContext()->Global(). 2. There is no String::New() and usually you want String::NewFromUTF8(). Don't think this justifies another answer but it'd be call if you update yours.Some of the node API's have changed from the publishing of the OP. Assuming a node.js version 7.7.1, the code transforms to something along the lines of;
std::string ToJson(v8::Local<v8::Value> obj)
{
if (obj.IsEmpty())
return std::string();
v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::HandleScope scope(isolate);
v8::Local<v8::Object> JSON = isolate->GetCurrentContext()->
Global()->Get(v8::String::NewFromUtf8(isolate, "JSON"))->ToObject();
v8::Local<v8::Function> stringify = JSON->Get(
v8::String::NewFromUtf8(isolate, "stringify")).As<v8::Function>();
v8::Local<v8::Value> args[] = { obj };
// to "pretty print" use the arguments below instead...
//v8::Local<v8::Value> args[] = { obj, v8::Null(isolate), v8::Integer::New(isolate, 2) };
v8::Local<v8::Value> const result = stringify->Call(JSON,
std::size(args), args);
v8::String::Utf8Value const json(result);
return std::string(*json);
}
Basically, the code gets the JSON object from the engine, obtains a reference to the function stringify of that object, and then calls it. The code is tantamount to the javascript;
var j = JSON.stringify(obj);
Further v8 based alternatives include using the JSON class.
auto str = v8::JSON::Stringify(v8::Isolate::GetCurrent()->GetCurrentContext(), obj).ToLocalChecked();
v8::String::Utf8Value json{ str };
return std::string(*json);