Search code examples
javascriptv8stringify

Using stringify from the v8 shell


I'm creating a v8 shell based console, I took the sample code that cames with v8 and it's working very well, but I'm trying to convert a v8::object to the string version of it (json) but didnt findout a way to do it.

Here's my sample code inside the 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("");
    }

At the shell I created a file test.js with this:



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

and I get this after executing the js within the shell console:



    [object Object]
    It's an object

What I want is:



    { "name": "John" }

if I change the js code to:



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

it works very well, but I dont want the user having to know how to parse a javascript variable into json, and I dont want to check for every single input at the object and parse it manually.

Is there a way to execute the same instruction inside the shell.cc code in C? something like:



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

update: This is how I'm handling this, but I want a cleaner way to do the same:



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


Solution

  • I found this way of doing the reverse (JSON to v8 object), using v8s built in JSON.parse function. http://www.mail-archive.com/[email protected]/msg04430.html

    Adjusting this to use JSON.stringify instead would look kind of like this (untested):

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