【问题标题】:Using stringify from the v8 shell在 v8 shell 中使用 stringify
【发布时间】:2012-02-18 00:14:12
【问题描述】:

我正在创建一个基于 v8 shell 的控制台,我采用了 v8 附带的示例代码,它运行良好,但我正在尝试将 v8::object 转换为它的字符串版本 (json) 但是没找到办法。

这是我在 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("");
    }

我在 shell 中创建了一个 test.js 文件:



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

我在 shell 控制台中执行 js 后得到这个:



    [object Object]
    It's an object

我想要的是:



    { "name": "John" }

如果我把js代码改成:



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

它工作得很好,但我不希望用户必须知道如何将 javascript 变量解析为 json,并且我不想检查对象的每个输入并手动解析它。

有没有办法在 C 语言的 shell.cc 代码中执行相同的指令?类似:



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

更新:这就是我的处理方式,但我想要一种更简洁的方式来做同样的事情:



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

【问题讨论】:

    标签: javascript v8 stringify


    【解决方案1】:

    我发现了这种相反的方式(JSON 到 v8 对象),使用内置于 JSON.parse 函数的 v8s。 http://www.mail-archive.com/v8-users@googlegroups.com/msg04430.html

    将其调整为使用 JSON.stringify 会看起来像这样(未经测试):

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

    【讨论】:

      【解决方案2】:

      我想避免使用现在已弃用的 V8 方法来实现我自己的 v8::Value-to-string 转换,所以我将这个函数放在一起,从 Michael 的回答中获得灵感。缺点是它非常冗长:

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

      【讨论】:

        【解决方案3】:

        如果您使用的是较新的 V8(如 8.3),代码如下:

        void static jsonStringify(v8::Local<v8::Context> context, v8::Local<v8::Value> value) {
          auto isolate = context->GetIsolate();
          auto global = context->Global();
          auto json = global->Get(context, v8::String::NewFromUtf8(isolate, "JSON", v8::NewStringType::kNormal).ToLocalChecked()).ToLocalChecked().As<v8::Object>();
          auto stringify = json->Get(context, v8::String::NewFromUtf8(isolate, "stringify", v8::NewStringType::kNormal).ToLocalChecked()).ToLocalChecked().As<v8::Function>();
          auto v = stringify->Call(context, Undefined(isolate), 1, &value).ToLocalChecked();
          v8::String::Utf8Value json_value(isolate, v);
          std::cout << "your json value" << &json_value;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-04-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-03-20
          • 2019-04-14
          • 1970-01-01
          • 2013-06-02
          相关资源
          最近更新 更多