SJSON (Streamed JSON) is a modern memory-optimized C++23 JSON parsing library that supports parsing JSON sent in a stream/chunks, forwarding & dropping values sent to listeners in a JSON stream, malformed syntax auto-correction, error recovery, and regular memory-optimized parsing of a JSON string.
- Parses JSON sent in individual chunks.
- Use this to avoid storing a massive string then spending lots of time parsing it all at once.
- This saves memory because you will no longer have to store the entire JSON string; only the individual chunks need to be in memory at any given time.
- This JSON parser prioritizes minimizing memory usage.
- The parser is non-recursive and discards unneeded tokens/syntax to save memory.
- This parser is perfect for dealing with massive amounts of data at a single time, or for low-spec machines.
- This JSON parser supports using listeners to run a callback for specific values, properties, or indexes after that specific value has been fully parsed.
- The parser supports listening generically, allowing a callback to run, for example, on every element of an array.
- The parser supports deallocating/dropping values sent to generic listeners, allowing you to have only one value of (for example an array) stored at a time during parse. This can massively save memory and increase performance on JSON that contains massive arrays.
- This parser can parse JSON with extremely minimal (and technically invalid) syntax due to the discarding of unneeded tokens. This allows you to parse much smaller JSON strings/streams.
- For example, the parser will parse
{"a"1"b"2}as{"a": 1, "b": 2}. - This parser supports error recovery, allowing you to read data parsed before an unrecoverable syntax error was encountered.
- You may use error recovery to, for example, parse JSON with no closing brackets and still parsing it perfectly.
- This parser also supports all of the above with normal strings, so you may have all the benefits without using a stream.
- This parser is fully RFC4627 compliant, aside from syntax auto-correction (https://www.rfc-editor.org/rfc/rfc4627.html)
To see all examples, go to the examples directory.
// examples/stream.cpp
#include "sjson.hpp"
#include "util.hpp"
int main() {
// Parse until the stream is finished and return the value
auto value = SJSON::Parse::stream(std::move(stream_example));
// Log the value as pretty print and have indents be 4 spaces
std::cout << "Finished parsed value: " << value.to_string(4) << '\n';
// You may `.to_string()` the value with no pretty print by giving no arguments
return 0;
}// examples/string.cpp
#include "sjson.hpp"
#include "util.hpp"
int main() {
// Parses and returns the value
auto value = SJSON::Parse::string(input_example);
// Log the value as pretty print and have indents be 4 spaces
std::cout << "Value of the JSON is: " << value.to_string(4) << '\n';
// You may `.to_string()` the value with no pretty print by giving no arguments
return 0;
}// examples/listeners.cpp
#include "sjson.hpp"
#include "util.hpp"
int main() {
// Define the stream; no parsing is done until told to
SJSON::Parse json(std::move(stream_example), true); // Boolean here tells the parser if it should drop values sent to generic listeners
json
.listen("test[]", [](const SJSON::JSValue& value) {
std::cout << "Generic value in 'test': " << value.to_string(4) << '\n';
})
.listen("test", [](const SJSON::JSValue& value) {
// Array will be empty due to the generic callback dropping the elements
std::cout << "Value of 'test': " << value.to_string(4) << '\n';
});
// Start parsing one iteration a time; you could also use the `.all()` method to parse until the stream is finished
for (int i = 0; json.next(); i++) {
std::cout << "JSON Stream iteration #" << i << '\n';
}
// Result should be of value `{"test":[]}` because dropped values aren't stored
std::cout << "Finished parsed value: " << json.to_string(4) << '\n';
return 0;
}// examples/recovery.cpp
#include "sjson.hpp"
#include "util.hpp"
int main() {
/*
This example is for streams only because
a string argument is parsed inside the constructor
*/
// Define the stream without parsing
SJSON::Parse stream(std::move(error_stream_example));
try {
// Try to parse the entire stream
stream.all();
} catch (SJSON::sjson_parse_error err) {
// Catch the input error
std::cout << "Error with the input stream during parse:\n"
<< "\tsjson_parse_error.what(): " << err.what() << '\n';
}
// Log what was parsed before the error as pretty print with indents of 4 spaces
std::cout << "Data parsed before error is: " << stream.to_string(4) << '\n';
return 0;
}typedef std::move_only_function<void(const JSValue& value)> JSONCallbacktypedef std::move_only_function<std::string()> JSONStreamtypedef std::monostate JSNulltypedef double JSNumbertypedef bool JSBooleantypedef std::string JSStringtypedef std::map<std::string, JSValue> JSObjecttypedef std::vector<JSValue> JSArrayusing JSValueData = std::variant<JSNull, JSNumber, JSBoolean, JSString, JSObject, JSArray>
Parse(JSONStream&& src, bool drop_generics = false)Parse(const std::string& src)static JSValue string(const std::string& src)static JSValue stream(JSONStream&& src)Parse& listen(const std::string& label, JSONCallback&& cb)bool next()void all()std::string to_string(int index_length = 0) const
JSValue() = defaultJSValue(JSNull v)JSValue(JSNumber v)JSValue(int v)JSValue(long v)JSValue(unsigned long v)JSValue(JSBoolean v)JSValue(const JSString& v)JSValue(const std::string_view& v)JSValue(const char* v)JSValue(const JSObject& v)JSValue(const JSArray& v)JSValueType type() constconst char* type_str() const noexceptbool is_null() const noexceptbool is_number() const noexceptbool is_boolean() const noexceptbool is_string() const noexceptbool is_object() const noexceptbool is_array() const noexceptstd::string to_string(int index_length = 0, int index = 1) constJSNull& null()JSNumber& number()JSBoolean& boolean()JSString& string()JSObject& object()JSArray& array()const JSNull& null() constconst JSNumber& number() constconst JSBoolean& boolean() constconst JSString& string() constconst JSObject& object() constconst JSArray& array() const