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

时间:2014-05-14 23:19:27

标签: c++ json 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));
}

崩溃的特定网站=&gt;

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

4 个答案:

答案 0 :(得分:6)

您可以使用通过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())

希望这有帮助。

答案 1 :(得分:3)

以下代码应该可以使用,只要您使用的是较早的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;
}

答案 2 :(得分:1)

如果您正在编写本机节点模块并使用 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();

答案 3 :(得分:0)

我添加了这个额外的答案,因为我之前的答案仍然是正确的,但截至目前,已有更新更好的答案。

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

Nan::JSON对象提供了javascript中JSON对象提供的方法的c ++版本,其向后兼容 NAN 支持的所有Node.js版本。 EM>。否则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 JSON版本的详细信息,请参阅V8 documentation中的V8对象。

上述内容是从NAN documentation

转述的