Created
May 12, 2020 16:23
-
-
Save harpagon210/deefb4fc88b2bc22756e3cb011762e4a to your computer and use it in GitHub Desktop.
nodejs native module JSON parser/stringifier (native implementation vs rapidjson)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "JSON.h" | |
#include <iostream> | |
#include <chrono> | |
Napi::Value JSON::DocumentToValue(Napi::Env env, rapidjson::Value document) | |
{ | |
if (document.IsString()) | |
{ | |
return Napi::String::New(env, document.GetString()); | |
} | |
else if (document.IsBool()) | |
{ | |
return Napi::Boolean::New(env, document.GetBool()); | |
} | |
else if (document.IsDouble()) | |
{ | |
return Napi::Number::New(env, document.GetDouble()); | |
} | |
else if (document.IsNull()) | |
{ | |
return env.Null(); | |
} | |
else if (document.IsArray()) | |
{ | |
rapidjson::Value::Array doc = document.GetArray(); | |
int length = doc.Size(); | |
Napi::Array array = Napi::Array::New(env, length); | |
int i; | |
for (i = 0; i < length; i++) | |
{ | |
if (doc[i].IsString()) | |
{ | |
array.Set(i, Napi::String::New(env, doc[i].GetString())); | |
} | |
else if (doc[i].IsBool()) | |
{ | |
array.Set(i, Napi::Boolean::New(env, doc[i].GetBool())); | |
} | |
else if (doc[i].IsDouble()) | |
{ | |
array.Set(i, Napi::Number::New(env, doc[i].GetDouble())); | |
} | |
else if (doc[i].IsArray()) | |
{ | |
array.Set(i, JSON::DocumentToValue(env, doc[i].GetArray())); | |
} | |
else if (doc[i].IsObject()) | |
{ | |
array.Set(i, JSON::DocumentToValue(env, doc[i].GetObject())); | |
} | |
else | |
{ | |
array.Set(i, env.Null()); | |
} | |
} | |
return array; | |
} | |
else if (document.IsObject()) | |
{ | |
Napi::Object obj = Napi::Object::New(env); | |
for (rapidjson::Value::MemberIterator itr = document.MemberBegin(); itr != document.MemberEnd(); ++itr) | |
{ | |
std::string key = itr->name.GetString(); | |
if (itr->value.IsString()) | |
{ | |
obj.Set(key, Napi::String::New(env, itr->value.GetString())); | |
} | |
else if (itr->value.IsBool()) | |
{ | |
obj.Set(key, Napi::Boolean::New(env, itr->value.GetBool())); | |
} | |
else if (itr->value.IsDouble()) | |
{ | |
obj.Set(key, Napi::Number::New(env, itr->value.GetDouble())); | |
} | |
else if (itr->value.IsArray()) | |
{ | |
obj.Set(key, JSON::DocumentToValue(env, itr->value.GetArray())); | |
} | |
else if (itr->value.IsObject()) | |
{ | |
obj.Set(key, JSON::DocumentToValue(env, itr->value.GetObject())); | |
} else | |
{ | |
obj.Set(key, env.Null()); | |
} | |
} | |
return obj; | |
} | |
} | |
Napi::Value JSON::Parse(Napi::Env env, std::string json_string) | |
{ | |
Napi::Value value = Napi::Value(); | |
rapidjson::Document document; | |
document.Parse(json_string.c_str()); | |
if (!document.HasParseError()) | |
{ | |
value = JSON::DocumentToValue(env, document.GetObject()); | |
} | |
return value; | |
} | |
Napi::Value JSON::ParseNative(Napi::Env env, Napi::String json_string) | |
{ | |
Napi::Object json = env.Global().Get("JSON").As<Napi::Object>(); | |
Napi::Function parse = json.Get("parse").As<Napi::Function>(); | |
Napi::Value val = parse.Call(json, {json_string}); | |
return val; | |
} | |
Napi::Value JSON::StringifyNative(Napi::Env env, Napi::Value json_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}); | |
} | |
void JSON::ValueToString(rapidjson::Writer<rapidjson::StringBuffer> &writer, Napi::Value value) | |
{ | |
if (value.IsNull()) | |
{ | |
writer.Null(); | |
} | |
else if (value.IsUndefined()) | |
{ | |
// don't stringify | |
} | |
else if (value.IsArray()) | |
{ | |
writer.StartArray(); | |
Napi::Array array = value.As<Napi::Array>(); | |
for (uint32_t i = 0; i < array.Length(); i++) | |
{ | |
Napi::Value val = array.Get(i); | |
JSON::ValueToString(writer, val); | |
} | |
writer.EndArray(); | |
} | |
else if (value.IsObject()) | |
{ | |
writer.StartObject(); | |
Napi::Object obj = value.As<Napi::Object>(); | |
Napi::Array props = obj.GetPropertyNames(); | |
for (uint32_t i = 0; i < props.Length(); i++) | |
{ | |
std::string key = props.Get(i).ToString(); | |
Napi::Value val = obj.Get(key); | |
if (!val.IsUndefined()) | |
{ | |
writer.String(key.c_str()); | |
JSON::ValueToString(writer, val); | |
} | |
} | |
writer.EndObject(); | |
} | |
else if (value.IsBoolean()) | |
{ | |
Napi::Boolean val = value.As<Napi::Boolean>(); | |
writer.Bool(val.ToBoolean()); | |
} | |
else if (value.IsNumber()) | |
{ | |
Napi::Number val = value.As<Napi::Number>(); | |
writer.Double(val.DoubleValue()); | |
} | |
else | |
{ | |
Napi::String val = value.As<Napi::String>(); | |
std::string str = val.ToString(); | |
writer.String(str.c_str()); | |
} | |
} | |
std::string JSON::Stringify(Napi::Value json_object) | |
{ | |
rapidjson::StringBuffer buffer; | |
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer); | |
JSON::ValueToString(writer, json_object); | |
return buffer.GetString(); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef JSON_H | |
#define JSON_H | |
#include <napi.h> | |
#include "thirdparty/rapidjson/document.h" | |
#include "thirdparty/rapidjson/writer.h" | |
#include "thirdparty/rapidjson/stringbuffer.h" | |
class JSON | |
{ | |
public: | |
static Napi::Value DocumentToValue(Napi::Env env, rapidjson::Value document); | |
static Napi::Value ParseNative(Napi::Env env, Napi::String json_string); | |
static Napi::Value Parse(Napi::Env env, std::string json_string); | |
static void ValueToString(rapidjson::Writer<rapidjson::StringBuffer> &writer, Napi::Value value); | |
static std::string Stringify(Napi::Value json_object); | |
static Napi::Value StringifyNative(Napi::Env env, Napi::Value json_object); | |
}; | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment