This code was written by Jim McCann (ix), and is released under the MIT license. The latest version of this code is available at https://github.com/ixchow/sejp.
SEJP is a Somewhat Eager JSON Parser for C++ -- it reads JSON file from a stream and makes it into dynamically-typed values as it does so. It is a small and reasonably lightweight piece of code (easy to audit and integrate!).
However, it does parse and hold the entire file in memory; so is not particularly suited to streaming access of very large files.
Usage example:
#include "sejp.hpp"
#include <iostream>
int main(int argc, char **argv) {
std::string json =
"{\n"
" \"version\":15,\n"
" \"places\":[\n"
" \"Pittsburgh, PA\","
" \"Salt Lake City, UT\""
" ],\n"
" \"extra\":{\n"
" \"optimized\":false,\n"
" \"debug\":true\n"
" },\n"
" \"more\":null\n"
"}\n"
;
sejp::value val = sejp::parse(json);
{ //simple example -- if you know what you are accessing:
//if you are sure: (will throw if key is missing)
double version = val.as_object().value().at("version").as_number().value();
std::cout << "Version is " << version << "." << std::endl;
}
//if you try to get the value of something at the wrong type, an exception is thrown:
try {
//NOTE: this will fail!
double inversion = val.as_object().value().at("inversion").as_number().value();
std::cout << "ERROR -- got " << inversion << " instead of failing." << std::endl;
} catch (std::exception &e) {
std::cout << "SUCCESS -- key \"inversion\" doesn't exist. (Reported as: " << e.what() << ".)" << std::endl;
}
// a more complete example:
//you can do this because the returned optionals are valid as long as some value from the parse is held:
std::map< std::string, sejp::value > const &object = val.as_object().value();
double version = object.at("version").as_number().value();
std::cout << "Version is " << version << std::endl;
//if a "places" key exists...
if (auto places = object.find("places"); places != object.end()) {
//...coerce to an array (will throw if not) and iterate:
for (auto const &place : places->second.as_array().value()) {
std::cout << " Place: " << place.as_string().value() << std::endl;
}
}
}
Values keep a shared_ptr
to the parsed data, and return references into these arrays. This means that one can safely hold references to (e.g.) value.as_array().value()
as long as value
remains alive.
Copy sejp.hpp
and sejp.cpp
into your project.
Make sure to build with (at least) c++17 support, since this code uses std::optional< >
.