From b4a6ca3487ae18e2fd75f9c2b3bedb1c7aea0d40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Tomic=CC=8Cevic=CC=81?= <dominik.tomicevic@gmail.com> Date: Sun, 21 Jun 2015 21:15:46 +0200 Subject: [PATCH] added a JSON class --- data_model/json/all.hpp | 14 +++++ data_model/json/array.hpp | 84 +++++++++++++++++++++++++++ data_model/json/bool.hpp | 33 +++++++++++ data_model/json/integral.hpp | 33 +++++++++++ data_model/json/json.hpp | 47 +++++++++++++++ data_model/json/null.hpp | 30 ++++++++++ data_model/json/object.hpp | 106 ++++++++++++++++++++++++++++++++++ data_model/json/primitive.hpp | 29 ++++++++++ data_model/json/real.hpp | 33 +++++++++++ data_model/json/string.hpp | 34 +++++++++++ 10 files changed, 443 insertions(+) create mode 100644 data_model/json/all.hpp create mode 100644 data_model/json/array.hpp create mode 100644 data_model/json/bool.hpp create mode 100644 data_model/json/integral.hpp create mode 100644 data_model/json/json.hpp create mode 100644 data_model/json/null.hpp create mode 100644 data_model/json/object.hpp create mode 100644 data_model/json/primitive.hpp create mode 100644 data_model/json/real.hpp create mode 100644 data_model/json/string.hpp diff --git a/data_model/json/all.hpp b/data_model/json/all.hpp new file mode 100644 index 000000000..eb179eadd --- /dev/null +++ b/data_model/json/all.hpp @@ -0,0 +1,14 @@ +#ifndef JSON_ALL_HPP +#define JSON_ALL_HPP + +#include "array.hpp" +#include "bool.hpp" +#include "integral.hpp" +#include "json.hpp" +#include "null.hpp" +#include "object.hpp" +#include "primitive.hpp" +#include "real.hpp" +#include "string.hpp" + +#endif diff --git a/data_model/json/array.hpp b/data_model/json/array.hpp new file mode 100644 index 000000000..bd0ef1a76 --- /dev/null +++ b/data_model/json/array.hpp @@ -0,0 +1,84 @@ +#ifndef JSON_ARRAY_HPP +#define JSON_ARRAY_HPP + +#include <cassert> +#include <memory> +#include <vector> + +#include "../utilities/utils.hpp" + +#include "json.hpp" + +namespace json +{ + +class Array final : public Json +{ +public: + Array() {} + + template <typename It> + Array(It first, It last) + : elements(first, last) {} + + Array(std::initializer_list<spJson> elements) + : elements(elements) {} + + virtual bool is_array() const; + + size_t size() const; + + Array& push(const std::shared_ptr<Json>& element); + + const spJson& operator[](size_t i) const; + spJson operator[](size_t i); + + virtual operator std::string() const; + +private: + std::vector<spJson> elements; +}; + +bool Array::is_array() const +{ + return true; +} + +size_t Array::size() const +{ + return elements.size(); +} + +Array& Array::push(const spJson& element) +{ + assert(element); + + elements.push_back(element); + return *this; +} + +const spJson& Array::operator[](size_t i) const +{ + return elements[i]; +} + +spJson Array::operator[](size_t i) +{ + return elements[i]; +} + +Array::operator std::string() const +{ + std::vector<std::string> xs; + + std::transform(elements.begin(), elements.end(), std::back_inserter(xs), + [](const spJson& element) { + return static_cast<std::string>(*element); + }); + + return "[" + utils::intercalate(xs.begin(), xs.end(), ",") + "]"; +} + +} + +#endif diff --git a/data_model/json/bool.hpp b/data_model/json/bool.hpp new file mode 100644 index 000000000..f91d1f20f --- /dev/null +++ b/data_model/json/bool.hpp @@ -0,0 +1,33 @@ +#ifndef JSON_BOOL_HPP +#define JSON_BOOL_HPP + +#include "primitive.hpp" + +namespace json { + +class Bool final : public Primitive<bool> +{ +public: + Bool() {} + + Bool(bool value) + : Primitive<bool>(value) {} + + virtual bool is_boolean() const; + + virtual operator std::string() const; +}; + +bool Bool::is_boolean() const +{ + return true; +} + +Bool::operator std::string() const +{ + return value == true ? "true" : "false"; +} + +} + +#endif diff --git a/data_model/json/integral.hpp b/data_model/json/integral.hpp new file mode 100644 index 000000000..fd961ebbd --- /dev/null +++ b/data_model/json/integral.hpp @@ -0,0 +1,33 @@ +#ifndef JSON_INTEGRAL_HPP +#define JSON_INTEGRAL_HPP + +#include "primitive.hpp" + +namespace json { + +class Integral final : public Primitive<int64_t> +{ +public: + Integral() {} + + Integral(int64_t value) + : Primitive<int64_t>(value) {} + + virtual bool is_integral() const; + + virtual operator std::string() const; +}; + +bool Integral::is_integral() const +{ + return true; +} + +Integral::operator std::string() const +{ + return std::to_string(value); +} + +} + +#endif diff --git a/data_model/json/json.hpp b/data_model/json/json.hpp new file mode 100644 index 000000000..f966b841a --- /dev/null +++ b/data_model/json/json.hpp @@ -0,0 +1,47 @@ +#ifndef JSON_JSON_HPP +#define JSON_JSON_HPP + +#include <initializer_list> +#include <string> +#include <memory> + +namespace json { + +class Json; + +typedef std::shared_ptr<Json> spJson; + +class Json +{ +public: + Json() {} + virtual ~Json() {} + + virtual bool is_object() const { return false; } + virtual bool is_array() const { return false; } + virtual bool is_real() const { return false; } + virtual bool is_integral() const { return false; } + virtual bool is_boolean() const { return false; } + virtual bool is_null() const { return false; } + + template <typename T> T& as(); + template <typename T> const T& as() const; + + virtual operator std::string() const = 0; +}; + +template <typename T> +T& Json::as() +{ + return *dynamic_cast<T*>(this); +} + +template <typename T> +const T& Json::as() const +{ + return *dynamic_cast<T*>(this); +} + +} + +#endif diff --git a/data_model/json/null.hpp b/data_model/json/null.hpp new file mode 100644 index 000000000..982363e4e --- /dev/null +++ b/data_model/json/null.hpp @@ -0,0 +1,30 @@ +#ifndef JSON_NULL_HPP +#define JSON_NULL_HPP + +#include "json.hpp" + +namespace json { + +class Null final : public Json +{ +public: + Null() {} + + virtual bool is_null() const; + + virtual operator std::string() const; +}; + +bool Null::is_null() const +{ + return true; +} + +Null::operator std::string() const +{ + return "null"; +} + +} + +#endif diff --git a/data_model/json/object.hpp b/data_model/json/object.hpp new file mode 100644 index 000000000..5ecbbc378 --- /dev/null +++ b/data_model/json/object.hpp @@ -0,0 +1,106 @@ +#ifndef JSON_OBJECT_HPP +#define JSON_OBJECT_HPP + +#include <iostream> + +#include <functional> +#include <sstream> +#include <cassert> +#include <vector> +#include <map> + +#include "../utilities/utils.hpp" + +#include "json.hpp" + +namespace json { + +typedef std::pair<const std::string, spJson> const_kv_pair_t; +typedef std::pair<std::string, spJson> kv_pair_t; + +class Object; + +typedef std::shared_ptr<Object> spObject; + +class Object : public Json +{ +public: + Object() {} + + Object(std::initializer_list<const_kv_pair_t> elements) + : props(elements) {} + + virtual bool is_object() const; + + const spJson& at(const std::string& key) const; + spJson at(const std::string& key); + + const spJson& operator[](const std::string& key) const; + spJson operator[](const std::string& key); + + Object& put(const std::string& key, spJson value); + + Object& operator<<(const kv_pair_t& kv_pair); + + virtual operator std::string() const; + +protected: + std::map<std::string, spJson> props; +}; + +bool Object::is_object() const +{ + return true; +} + +const spJson& Object::at(const std::string& key) const +{ + return props.at(key); +} + +spJson Object::at(const std::string& key) +{ + return props.at(key); +} + +const spJson& Object::operator[](const std::string& key) const +{ + return this->at(key); +} + +spJson Object::operator[](const std::string& key) +{ + return this->at(key); +} + +Object& Object::put(const std::string& key, spJson value) +{ + assert(value); + + props[key] = value; + return *this; +} + +Object& Object::operator<<(const kv_pair_t& kv_pair) +{ + return this->put(std::get<0>(kv_pair), std::get<1>(kv_pair)); +} + +Object::operator std::string() const +{ + if(props.empty()) + return "{}"; + + std::vector<std::string> xs; + + std::transform(props.begin(), props.end(), std::back_inserter(xs), + [](const kv_pair_t& kvp) { + return "\"" + kvp.first + "\":" + static_cast<std::string>(*kvp.second); + }); + + return "{" + utils::intercalate(xs.begin(), xs.end(), ",") + "}"; +} + +} + +#endif diff --git a/data_model/json/primitive.hpp b/data_model/json/primitive.hpp new file mode 100644 index 000000000..a0da326a8 --- /dev/null +++ b/data_model/json/primitive.hpp @@ -0,0 +1,29 @@ +#ifndef JSON_PRIMITIVE +#define JSON_PRIMITIVE + +#include "json.hpp" + +namespace json { + +template <class T> +class Primitive : public Json +{ +public: + Primitive() {} + + Primitive(const T& value) + : value(value) {} + + T get() const { return value; } + void set(T value) { this->value = value; } + + operator T() const { return this->get(); } + +protected: + T value; +}; + + +} + +#endif diff --git a/data_model/json/real.hpp b/data_model/json/real.hpp new file mode 100644 index 000000000..e3e5d3eff --- /dev/null +++ b/data_model/json/real.hpp @@ -0,0 +1,33 @@ +#ifndef JSON_REAL_HPP +#define JSON_REAL_HPP + +#include "primitive.hpp" + +namespace json { + +class Real final : public Primitive<float> +{ +public: + Real() {} + + Real(float value) + : Primitive<float>(value) {} + + virtual bool is_real() const; + + virtual operator std::string() const; +}; + +bool Real::is_real() const +{ + return true; +} + +Real::operator std::string() const +{ + return std::to_string(value); +} + +} + +#endif diff --git a/data_model/json/string.hpp b/data_model/json/string.hpp new file mode 100644 index 000000000..5fdd5b27d --- /dev/null +++ b/data_model/json/string.hpp @@ -0,0 +1,34 @@ +#ifndef JSON_STRING_HPP +#define JSON_STRING_HPP + +#include "primitive.hpp" + +namespace json +{ + +class String final : public Primitive<std::string> +{ +public: + String() {} + + String(const std::string& value) + : Primitive<std::string>(value) {} + + virtual bool is_string() const; + + virtual operator std::string() const; +}; + +bool String::is_string() const +{ + return true; +} + +String::operator std::string() const +{ + return "\"" + value + "\""; +} + +} + +#endif