From f7a7e6ce3981fe2afe49a7fcba60261f867adbf2 Mon Sep 17 00:00:00 2001 From: CismonX Date: Sat, 10 Mar 2018 10:28:54 +0800 Subject: [PATCH] archive --- LICENSE | 21 +++++++ README.md | 65 +++++++++++++++++++++ json.hpp | 172 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 258 insertions(+) create mode 100644 LICENSE create mode 100644 README.md create mode 100644 json.hpp diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..83a5457 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 CismonX + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..387bb09 --- /dev/null +++ b/README.md @@ -0,0 +1,65 @@ +# boost-helper-json +A simple wrapper around `Boost.PropertyTree` for quick & dirty JSON access. + +## 1. Introduction + +If you're working with JSON on C++ and looking for a good library, I'd recommend [RapidJSON](http://rapidjson.org/) or [JSON for Modern C++](https://nlohmann.github.io/json/). They are fast and scalable, and provide loads of useful functionalities. + +However, if you're just looking for a quick and dirty workaround, and happen to be using the Boost C++ libraries in your project, this may be an option for you. + +Just include the header, and start hacking with JSON. + +## 2. Example + +```c++ +#include "json.hpp" + +#include +#include + +int main() +{ + using namespace boost_helper; + + // Initialize JSON with a string. + json response(R"({"err":0,"data":{"msg":"ok","names":["John","Sarah"]}})"); + + // Changing a node value with a string. + response["data"]["msg"] = "confirmed"; + + // Check whether this node has a child with the specified key. + if (response.has("err")) + { + // Changing a node value with another JSON node. + response["err"] = json(R"({"code":0,"status":"ok"})"); + } + + // Access child node value of a JSON. + std::cout << "Now message becomes \"" << response["data"]["msg"].val() << '"' << std::endl; + + // Iterate through a JSON node. + for (const auto& name : response["data"]["names"]) + { + std::cout << name.second.val() << " said hello!" << std::endl; + } + + // Iterate througth a JSON node and change its children's values. + for (auto name : response["data"]["names"]) + { + name.second = "Nobody"; + } + + // Compare a JSON node with another node. + if (response["data"]["names"] == json(R"(["Nobody","Nobody"])")) + { + // Add a child string to a JSON node without key. + response["data"]["names"].add("Somebody"); + } + + // Add a child node to a JSON node without key. + response["data"]["names"].add(json(R"(["Paul","Joshua"])")); + + // Print a JSON node. + std::cout << response.to_string() << std::endl; +} +``` diff --git a/json.hpp b/json.hpp new file mode 100644 index 0000000..51a7315 --- /dev/null +++ b/json.hpp @@ -0,0 +1,172 @@ +#pragma once + +#include + +namespace boost_helper +{ + /** + * A simple wrapper around Boost.PropertyTree for quick & dirty JSON access. + * + * @author CismonX + */ + class json + { + using ptree = boost::property_tree::ptree; + + /// The Boost.PropertyTree instance with stores this JSON structure. + ptree* data_; + + /// Whether this is the node root of JSON object. + bool is_root_ = false; + + public: + /// Trying to modify the value of root node of JSON. + class root_modification_exception : public std::exception {}; + + /// Range-based for support. + class iterator : public ptree::iterator + { + public: + explicit iterator(const ptree::iterator& other) : ptree::iterator(other) {} + + std::pair operator*() const + { + return make_pair(dereference().first, json(&dereference().second)); + } + }; + + /** + * Iterator begin. + */ + iterator begin() const + { + return iterator(data_->begin()); + } + + /** + * Iterator end. + */ + iterator end() const + { + return iterator(data_->end()); + } + + /** + * Create a new JSON object with the given string. + */ + explicit json(const std::string& json_str) : is_root_(true) + { + data_ = new ptree; + std::istringstream stream(json_str); + read_json(stream, *data_); + } + + /** + * Create a JSON object with a ptree node. + */ + explicit json(boost::property_tree::ptree* other) : data_(other) {} + + /** + * Assign the value of this node with another node. + * @throws root_modification_exception : thrown when trying to modify a non-root node. + */ + json& operator=(const json& other) + { + if (is_root_) + throw root_modification_exception(); + *data_ = *other.data_; + return *this; + } + + /** + * Assign the value of this node with a string. + * @throws root_modification_exception : thrown when trying to modify a non-root node. + */ + json& operator=(const std::string& value) + { + if (is_root_) + throw root_modification_exception(); + data_->put_value(value); + return *this; + } + + /** + * Whether this node is equal to another node. + */ + bool operator==(const json& other) const + { + return *data_ == *other.data_; + } + + /** + * Whether this node is not equal to another node. + */ + bool operator!=(const json& other) const + { + return *data_ != *other.data_; + } + + /** + * Get child node. + */ + json operator[](const std::string& key) const + { + if (data_->find(key) == data_->not_found()) + data_->add_child(key, boost::property_tree::ptree()); + return json(&data_->get_child(key)); + } + + /** + * Add a string element to this node without key. + */ + void add(const std::string& value) + { + ptree element; + element.put_value(value); + data_->push_back(make_pair("", element)); + } + + /** + * Add a child node to this node without key. + */ + void add(const json& value) + { + data_->push_back(make_pair("", *value.data_)); + } + + /** + * Get string value of this node. + */ + std::string val() const + { + return data_->get_value(); + } + + /** + * Check whether this node has a child with the specified key. + */ + bool has(const std::string& key) const + { + return data_->find(key) != data_->not_found(); + } + + /** + * Print this JSON node to a string. + */ + std::string to_string(bool pretty = false) const + { + std::ostringstream stream; + write_json(stream, *data_, pretty); + return stream.str(); + } + + /** + * Destructor. + */ + ~json() + { + if (is_root_) + delete data_; + } + }; +}