From 815d94931b792a8add1fc90b027ea37f17ced037 Mon Sep 17 00:00:00 2001 From: DanielSchuette Date: Sun, 23 May 2021 03:31:17 +0200 Subject: [PATCH] update src/main.cc example, include snippet in README.md --- README.md | 48 +++++++++++++++++++++++++++++++++++++++--------- data/test.json | 2 +- src/main.cc | 25 ++++++++++++++++++++----- 3 files changed, 60 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index a2c9bb9..06ae2fb 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@

- +

-# Simple-JSON-Parser (SJP) -`SJP` is a minimal JSON parser that (almost) fully implements the JSON spec at +# Simple-JSON-Parser (sjp) +`sjp` is a minimal JSON parser that (almost) fully implements the JSON spec at [www.json.org](https://www.json.org/json-en.html). It is written in fairly clean C++ and the interface is designed to make data from a JSON file easily accessible without a complicated API or any extra dependencies. The following @@ -54,16 +54,46 @@ requirement. You can verify the fact that we don't leak any allocations with `make leak-test` (requires `valgrind`). # Usage Example -Take a look at `main.cc` for an example of how to use `SJP`. A -[Makefile](./src/Makefile) is provided (again, my setup with `gcc` as the -compiler). Run the following in the repository's base directory: +Take a look at [`src/main.cc`](./src/main.cc) for an example of how to use +`sjp`. A [Makefile](./src/Makefile) is provided (again, my setup with `gcc` as +the compiler). Run `make test` to see what `sjp` can do for you. -```bash -make test +Here's a snippet, taken from that file: + +```c++ +{ + FILE* stream = fopen("some/file.json", "r"); + auto logger = io::SjpLogger(*argv, stderr); + auto parser = sjp::Parser(stream, &logger); + + sjp::Json json = parser.parse(); + json.print(stderr); // pretty-prints the parsed JSON to a FILE* + + /* Now, we can read data from the SJP::JSON object. + * JSONOBJECTs are accessed via OPERATOR[] and string keys. + */ + sjp::JsonValue& array = json["data"]["deeply"]["nested"]; + assert(array.get_type() == sjp::Type::Array); + + std::vector v; + for (size_t i = 0; i < array.size(); i++) { + /* JSONARRAYs are accessed via OPERATOR[] and integer keys. + * We get a JSONVALUE&, which we must cast to the actual type before + * the VALUE member (that every primitive type has) can be accessed. + * As seen above, we can always check JSONVALUE.GET_TYPE() to + * dynamically validate what kind of data we've got. + */ + sjp::JsonNumber& n = static_cast(array[i]); + v.push_back(n.value); + } +} ``` +`sjp` only has a few API functions you need to know about and those are pretty +much all demonstrated in [`src/main.cc`](./src/main.cc). + Since we don't link any external dependencies in, any IDE should be easily able -to compile the code, too. When you use `SJP` as a library, simply copy `src/*` +to compile the code, too. When you use `sjp` as a library, simply copy `src/*` into your project and include `sjp.hh` and `io.hh` where you need the parser and/or the `JSON` object. Yes, It is honestly __that__ easy! diff --git a/data/test.json b/data/test.json index d73bdfa..a6f5ed3 100644 --- a/data/test.json +++ b/data/test.json @@ -21,7 +21,7 @@ }, "data": { "deeply": { - "nested": [-0.124, 4230.0, 3.1415, 0, 1, 2, 3, 4] + "nested": [-0.124, 4230.0, 3.1415, 0, 1, 2, 3, 4, "a string, not a number"] } } } diff --git a/src/main.cc b/src/main.cc index 660cc0d..7e33389 100644 --- a/src/main.cc +++ b/src/main.cc @@ -33,20 +33,35 @@ int main(int /*argc*/, char** argv) auto parser = sjp::Parser(stream, &logger); sjp::Json json = parser.parse(); - json.print(stderr); + json.print(stderr); // pretty-prints the parsed JSON to a FILE* - std::vector v; + /* Now, we can read data from the SJP::JSON object. + * JSONOBJECTs are accessed via OPERATOR[] and string keys. + */ sjp::JsonValue& array = json["data"]["deeply"]["nested"]; assert(array.get_type() == sjp::Type::Array); + std::vector v; for (size_t i = 0; i < array.size(); i++) { - sjp::JsonNumber& n = static_cast(array[i]); - v.push_back(n.value); + /* JSONARRAYs are accessed via OPERATOR[] and integer keys. + * We get a JSONVALUE&, which we must cast to the actual type before + * the VALUE member (that every primitive type has) can be accessed. + * As seen above, we can always check JSONVALUE.GET_TYPE() to + * dynamically validate what kind of data we've got. + */ + sjp::JsonValue& item = array[i]; + if (item.get_type() == sjp::Type::Number) { + sjp::JsonNumber& n = static_cast(item); + v.push_back(n.value); + } else { + logger.warn("ignoring non-number item of type `%s'", + item.type_to_string().c_str()); + } } double s = 0.0; std::for_each(v.begin(), v.end(), [&s](const double&d) { s += d; }); - fprintf(stderr, "%g\n", s); + logger.log("sum over all number items in the array: %g", s); fclose(stream);