繁体   English   中英

如何在嵌入式v8中解析JSON?

[英]How to parse JSON in an embedded v8?

我试图在我的嵌入式V8应用程序中解析JS,我总是得到一个SIGSEGV。 我不确定发生了什么。

我解析json的代码,

v8::Handle<v8::Value> FromJSONString(
    v8::Handle<v8::Value> json_string) {
  v8::HandleScope scope;
  v8::Handle<v8::Context> context = v8::Context::GetCurrent();
  v8::Handle<v8::Object> global = context->Global();

  v8::Handle<v8::Value> JSON_value = global->Get(v8::String::New("JSON"));
  if (!IsObject(JSON_value)) {
    return scope.Close(v8::Undefined());
  }
  v8::Handle<v8::Object> JSON  = JSON_value->ToObject();

  v8::Handle<v8::Value> JSON_parse_value = JSON->Get(v8::String::New("parse"));

  if (JSON_parse_value.IsEmpty() || JSON_parse_value->IsNull() ||
      JSON_parse_value->IsUndefined() ||!JSON_parse_value->IsFunction()) {
    return scope.Close(v8::Undefined());
  }


  v8::Handle<v8::Function> JSON_parse =
      v8::Handle<v8::Function>::Cast(JSON_parse_value);

  return scope.Close(JSON_parse->Call(JSON, 1, &json_string));
}

崩溃的具体网站=>

bool extractSource(std::string* source, std::string& body) {
    v8::HandleScope scope; // this is needed and clears the memory
    if (body.empty()) {
        return false;
    }
    v8::Handle<v8::Value> value = v8_server_utils::FromJSONString(body);
    if (value->IsEmpty()) { // CRASHES HERE.
        return false;
    }
    if (value->IsNull()) {
        return false;
    }
    if (value->IsUndefined()) {
        return false;
    }
    if (!value->IsObject()) {
        return false;
    }
    auto object = value->ToObject();
    auto source_key = v8::String::New("source");
    if (object.IsEmpty() || object->IsNull() || object->IsUndefined() ||
        !object->Has(source_key)) {
        return false;
    }
    auto source_obj = object->Get(source_key);
    *source = v8_server_utils::JSStringToCString(source_obj->ToString());
    return true;
}

您可以使用通过API公开的JSON Parse函数:

v8::Local<v8::String> str; // some string
v8::Local<v8::Value> result = v8::JSON::Parse(str);

较新版本的V8提供了EscapableHandleScope您需要使用它来从函数返回句柄:

v8::EscapableHandleScope scope(isolate);
return scope.Escape(value);

这个

if (value->IsEmpty()) { // CRASHES HERE.

应该是

if (value.IsEmpty())

希望这可以帮助。

如果您使用的是较旧的V8版本,例如v3.14,则以下代码应该可以正常工作:

v8::Handle<v8::Value> FromJsonString (v8::Handle<v8::Value> jsonString) {
  v8::HandleScope scope;
  v8::Handle<v8::Context> context = v8::Context::GetCurrent();
  v8::Handle<v8::Object> global = context->Global();

  // find JSON object in global scope
  v8::Handle<v8::Value> jsonValue = global->Get(v8::String::New("JSON"));

  if (! jsonValue->IsObject()) {
    return scope.Close(v8::Undefined());
  }

  v8::Handle<v8::Object> json = jsonValue->ToObject();

  // find "parse" attribute
  v8::Handle<v8::Value> parse = json->Get(v8::String::New("parse"));

  if (parse.IsEmpty() ||
      ! parse->IsFunction()) {
    return scope.Close(v8::Undefined());
  }

  // cast into a function    
  v8::Handle<v8::Function> parseFunction = v8::Handle<v8::Function>::Cast(parse);

  // and call it
  return scope.Close(parseFunction->Call(json, 1, &jsonString));
}


static bool ExtractSource (std::string& source, std::string const& body) {
  v8::HandleScope scope;

  // convert whole body from cstring to V8 string
  v8::Handle<v8::String> bodyString = v8::String::New(body.c_str(), body.size());

  // call JSON.parse() on the body
  v8::Handle<v8::Value> value = FromJsonString(bodyString);

  // check if result is valid
  if (value.IsEmpty() ||
      value->IsNull() ||
      value->IsUndefined() ||
      ! value->IsObject()) {
    return false;
  }

  auto object = value->ToObject();

  // extract "source" attribute from result     
  auto sourceKey = v8::String::New("source");

  if (object.IsEmpty() || 
      object->IsNull() || 
      object->IsUndefined() ||
      ! object->Has(sourceKey)) {
    return false;
  }

  auto sourceValue = object->Get(sourceKey);

  if (! sourceValue->IsString()) {
    return false;
  }

  // convert the v8 string value into a cstring
  v8::String::Utf8Value sourceString(sourceValue->ToString());

  if (*sourceString == nullptr) {
    return false;
  }

  source.assign(*sourceString, sourceString.length());
  return true;
}

int main () {
  // test data
  std::string body = "{ \"body\": \"test\", \"source\": \"some string value\" }";
  // result
  std::string source;

  // call function and dump result
  std::cout << "is valid: " << ExtractSource(source, body) << std::endl;
  std::cout << "value of source: '" << source << "'" << std::endl;
}

如果您正在编写本机节点模块并使用NAN以便在所有主要版本的Node.js中支持它,那么我建议您尝试使用native-json npm包。

该包公开了以下方法:

static Nan::MaybeLocal<v8::Value> Native::JSON::Parse(v8::Local<v8::String> jsonString);

static Nan::MaybeLocal<v8::String> Native::JSON::Stringify(v8::Local<v8::Object> jsonObject, v8::Local<v8::String> gap = v8::Local<v8::String>())

至于NAN支持的节点版本中v8::JSON的更改:

v8::JSON::Parse最先可用的节点版本0.12.x -它不是在0.8版本或0.10.x否则可用

v8::JSON::Stringify首先在节点版本7中可用 - 在早期版本中不可

native-json包的Native::JSON单例类将以最有效的方式执行请求,具体取决于构建的Node.js的版本。 如果该方法在该版本的V8中可用,则将调用该方法。 否则, Native::JSON单例类会回退到从全局上下文中获取JSON对象。

源代码可在github存储库中找到: node-native-json

以下是如何使用Native::JSON::Parse的示例:

v8::Local<v8::String> json_string = Nan::New("{ \"JSON\": \"object\" }").ToLocalChecked();

v8::Local<v8::Value> val = Native::JSON::Parse(json_string).ToLocalChecked();

我正在添加这个额外的答案,因为我之前的答案仍然是正确的,但截至目前,可以获得更新更好的答案。

NAN版本2.6.2于2017年4月12日发布。此版本引入了一个新对象Nan::JSON

Nan::JSON对象提供由所提供的方法C ++版本JSON对象在JavaScript中,在某种程度上是由NAN Node.js的支持所有版本的向后兼容。 否则V8会通过v8::JSON对象公开这些方法。

楠:: JSON.Parse

围绕v8::JSON::Parse简单包装器。

定义:

Nan::MaybeLocal<v8::Value> Nan::JSON::Parse(v8::Local<v8::String> json_string);

使用JSON.Parse(json_string)将字符串解析为v8::Value

例:

v8::Local<v8::String> json_string = Nan::New("{ \"JSON\": \"object\" }").ToLocalChecked();

Nan::JSON NanJSON;
Nan::MaybeLocal<v8::Value> result = NanJSON.Parse(json_string);
if (!result.IsEmpty()) {
  v8::Local<v8::Value> val = result.ToLocalChecked();
}

楠:: JSON.Stringify

围绕v8::JSON::Stringify简单包装器。

定义:

Nan::MaybeLocal<v8::String> Nan::JSON::Stringify(v8::Local<v8::Object> json_object, v8::Local<v8::String> gap = v8::Local<v8::String>());

使用JSON.Stringify(value)来字符串化v8::Object

例:

v8::Local<v8::Object> obj = Nan::To<v8::Object>(val).ToLocalChecked();

Nan::JSON NanJSON;
Nan::MaybeLocal<v8::String> result = NanJSON.Stringify(obj);
if (!result.IsEmpty()) {
  v8::Local<v8::String> stringified = result.ToLocalChecked();
}

有关这些方法及其参数的原始V8版本的更多信息,请参阅V8文档中V8 JSON对象。

以上是从NAN文档中解释的

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM