Node.js N-API addon - how to stringify/parse JSON?
Asked Answered
D

1

8

I'm writing an addon for Node.js using N-API (the C interface, not to be confused with the node-addon-api C++ wrapper around N-API) which receives JSON-formatted data from an external source and needs to execute a JS callback function on its object form. However, I'm lost for a way to parse the JSON-formatted data into a proper object (i.e., resulting from JSON.parse) within the addon before passing it into the JS callback and can only seem to pass it on in its text form.

The only examples I've found so far that do this involve using the C++ NAN and V8 APIs directly. Am I missing something? Should I make another napi_call_function call to JSON.parse, capture its return value, then pass that on? (If so, how do I get the JSON.parse callback info from my addon?) Is there a simpler API that I've not found?

For many reasons, I'd prefer to stay in C, not C++, though I suppose that's negotiable.

foo.js

const myaddon = require('bindings')('myaddon');
const EventEmitter = require('events').EventEmitter;
const emitter = new EventEmitter();

emitter.on('eventReceived', (foo) => {
    var obj = JSON.parse(foo); // *** this is what I'd like to avoid ***
    console.log(obj.bar);
})

myaddon.RegisterForEvents(emitter.emit.bind(emitter));

myaddon.c

void AsyncComplete(napi_env env, napi_status status, void * data) {

    // do some work to get the JSON text from the external source,
    // setup argv with the necessary values:
    // argv[0]: "eventReceived"
    // argv[1]: JSON text -- would like to deserialize in addon, not in JS callback, so the JS callback receives a proper object

    // Execute the JS function
    napi_call_function(env, global /* from napi_get_global */, callback /* the emitter */, argc, argv, NULL);
    // ...
Desegregate answered 6/9, 2018 at 0:41 Comment(0)
B
7

Below is an example of how you could stringify and parse on the C++ end, rather than the Javascript end. Napi allows you to call javascript functions from C++ code. Below is an example of how to call JSON.stringify() & JSON.parse()

Napi::String JSONStringify(const Napi::CallbackInfo& info) {
  Napi::Env env = info.Env();
  Napi::Object json_object = info[0].As<Napi::Object>();
  Napi::Object json = env.Global().Get("JSON").As<Napi::Object>();
  Napi::Function stringify = json.Get("stringify").As<Napi::Function>();
  return stringify.Call(json, { json_object }).As<Napi::String>();
}

Napi::Object JSONParse(const Napi::CallbackInfo& info) {
  Napi::Env env = info.Env();
  Napi::String json_string = info[0].As<Napi::String>();
  Napi::Object json = env.Global().Get("JSON").As<Napi::Object>();
  Napi::Function parse = json.Get("parse").As<Napi::Function>();
  return parse.Call(json, { json_string }).As<Napi::Object>();
}

Napi::Object Init(Napi::Env env, Napi::Object exports) {
  exports["jsonStringify"] =  Napi::Function::New(env, JSONStringify);
  exports["jsonParse"] = Napi::Function::New(env, JSONParse);          
  return exports;
}

NODE_API_MODULE(json, Init)

Source: https://github.com/nodejs/node-addon-api/issues/410#issuecomment-574876170

Barron answered 16/1, 2020 at 20:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.