diff --git a/.github/workflows/io.yml b/.github/workflows/io.yml new file mode 100644 index 0000000..650d9e5 --- /dev/null +++ b/.github/workflows/io.yml @@ -0,0 +1,39 @@ +name: I/O Tests + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + test_io: + name: Build and Test I/O Examples + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: build JSON C++11 + run: g++ -std=c++11 -Wall -Wextra -Werror -O3 src/TinyJSON.cpp example/read_write_json.cpp -o rw_json_11 + + - name: run JSON C++11 + run: ./rw_json_11 + + - name: build JSON5 C++11 + run: g++ -std=c++11 -Wall -Wextra -Werror -O3 src/TinyJSON.cpp example/read_write_json5.cpp -o rw_json5_11 + + - name: run JSON5 C++11 + run: ./rw_json5_11 + + - name: build JSON C++20 + run: g++ -std=c++20 -Wall -Wextra -Werror -O3 src/TinyJSON.cpp example/read_write_json.cpp -o rw_json_20 + + - name: run JSON C++20 + run: ./rw_json_20 + + - name: build JSON5 C++20 + run: g++ -std=c++20 -Wall -Wextra -Werror -O3 src/TinyJSON.cpp example/read_write_json5.cpp -o rw_json5_20 + + - name: run JSON5 C++20 + run: ./rw_json5_20 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e8d3bbe..4b73fa4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -66,7 +66,7 @@ class Blah Enums are lower case ```cpp -enum class formating +enum class formatting { none, indented diff --git a/example/read_write_json.cpp b/example/read_write_json.cpp new file mode 100644 index 0000000..1683187 --- /dev/null +++ b/example/read_write_json.cpp @@ -0,0 +1,58 @@ +// Licensed to Florent Guelfucci under one or more agreements. +// Florent Guelfucci licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +#include "../src/TinyJSON.h" +#include +#include + +using namespace TinyJSON; + +int main() +{ + TJValueObject root; + root.set("project", "TinyJSON"); + root.set("version", 1); + root.set("fast", true); + + TJValueArray* arr = new TJValueArray(); + arr->add_number(100); + arr->add_number(200); + arr->add_number(300); + root.set("data", arr); + + TJValueObject* nested = new TJValueObject(); + nested->set("sub1", 1.5); + nested->set("sub2", "test string"); + root.set("metadata", nested); + + // Write to a file + std::string filename = "test_io_json.json"; + bool success = TinyJSON::TJ::write_file(filename.c_str(), root); + if (!success) { + std::cerr << "Failed to write JSON file." << std::endl; + return 1; + } + + // Read back the file + auto* parsed = TJ::parse_file(filename.c_str()); + if (!parsed) { + std::cerr << "Failed to read JSON file." << std::endl; + return 1; + } + + // Compare the dumped output to verify data matches + std::string original_dump = root.dump(formatting::minify); + std::string parsed_dump = parsed->dump(formatting::minify); + + if (original_dump != parsed_dump) { + std::cerr << "Data mismatch between original and read JSON!" << std::endl; + std::cerr << "Original: " << original_dump << std::endl; + std::cerr << "Parsed: " << parsed_dump << std::endl; + delete parsed; + return 1; + } + + std::cout << "Successfully wrote, read, and verified JSON file." << std::endl; + delete parsed; + return 0; +} diff --git a/example/read_write_json5.cpp b/example/read_write_json5.cpp new file mode 100644 index 0000000..bf3cdfa --- /dev/null +++ b/example/read_write_json5.cpp @@ -0,0 +1,77 @@ +// Licensed to Florent Guelfucci under one or more agreements. +// Florent Guelfucci licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +#include "../src/TinyJSON.h" +#include +#include + +using namespace TinyJSON; + +int main() +{ + const char* json5_content = R"({ + // This is a project name + project: 'TinyJSON', + version: 0x1, // Hex number + fast: true, + data: [ + /* multi line + comment */ + 100, + 200, + 300, // trailing comma + ], + metadata: { + sub1: +1.5, // Explicit plus + sub2: "test string", + } + })"; + + parse_options options; + options.specification = parse_options::json5_1_0_0; + + auto* root = TJ::parse(json5_content, options); + if (!root) { + std::cerr << "Failed to parse initial JSON5 content." << std::endl; + return 1; + } + + // Write to a file + std::string filename = "test_io_json5.json"; + write_options w_options; + w_options.write_formatting = formatting::indented; + bool success = TinyJSON::TJ::write_file(filename.c_str(), *root, w_options); + if (!success) { + std::cerr << "Failed to write JSON5 file." << std::endl; + delete root; + return 1; + } + + // Read back the file + // Since write_file outputs standard JSON (with comments preserved), + // we read it back using JSON5 specification to be safe. + auto* parsed = TJ::parse_file(filename.c_str(), options); + if (!parsed) { + std::cerr << "Failed to read JSON5 file." << std::endl; + delete root; + return 1; + } + + // Compare the dumped output to verify data matches + std::string original_dump = root->dump(formatting::minify); + std::string parsed_dump = parsed->dump(formatting::minify); + + if (original_dump != parsed_dump) { + std::cerr << "Data mismatch between original and read JSON5!" << std::endl; + std::cerr << "Original: " << original_dump << std::endl; + std::cerr << "Parsed: " << parsed_dump << std::endl; + delete root; + delete parsed; + return 1; + } + + std::cout << "Successfully wrote, read, and verified JSON5 file." << std::endl; + delete root; + delete parsed; + return 0; +}