10

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 2

5

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));
Sign up to request clarification or add additional context in comments.

1 Comment

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.
2

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.