Mercurial > code
changeset 484:3ee3f3e53ee3
Json: add brand new Value::toJson to stringify a value
author | David Demelier <markand@malikania.fr> |
---|---|
date | Thu, 12 Nov 2015 11:46:04 +0100 |
parents | 3f29e6c05983 |
children | 898d8b29a4f1 |
files | C++/modules/Json/Json.cpp C++/modules/Json/Json.h C++/tests/Json/main.cpp |
diffstat | 3 files changed, 170 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/C++/modules/Json/Json.cpp Thu Nov 12 08:57:21 2015 +0100 +++ b/C++/modules/Json/Json.cpp Thu Nov 12 11:46:04 2015 +0100 @@ -16,10 +16,13 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "Json.h" #include <jansson.h> +#include <sstream> + +#include "Json.h" + namespace json { namespace { @@ -107,6 +110,19 @@ return value; } +std::string indent(int param, int level) +{ + std::string str; + + if (param < 0) { + str = std::string(level, '\t'); + } else if (param > 0) { + str = std::string(param * level, ' '); + } + + return str; +} + } // !namespace void Value::copy(const Value &other) @@ -255,6 +271,65 @@ *this = convert(json_load_file, file.path.c_str(), 0); } +std::string Value::toJson(int level, int current) const +{ + std::ostringstream oss; + + switch (m_type) { + case Type::Array: { + oss << '[' << (level != 0 ? "\n" : ""); + + unsigned total = m_array.size(); + unsigned i = 0; + for (const auto &v : m_array) { + oss << indent(level, current + 1) << v.toJson(level, current + 1); + oss << (++i < total ? "," : ""); + oss << (level != 0 ? "\n" : ""); + } + + oss << (level != 0 ? indent(level, current) : "") << ']'; + break; + } + case Type::Boolean: + oss << (m_boolean ? true : false); + break; + case Type::Int: + oss << m_integer; + break; + case Type::Object: { + oss << '{' << (level != 0 ? "\n" : ""); + + unsigned total = m_object.size(); + unsigned i = 0; + for (const auto &pair : m_object) { + oss << indent(level, current + 1); + + /* Key and : */ + oss << "\"" << pair.first << "\":" << (level != 0 ? " " : ""); + + /* Value */ + oss << pair.second.toJson(level, current + 1); + + /* Comma, new line if needed */ + oss << (++i < total ? "," : "") << (level != 0 ? "\n" : ""); + } + + oss << (level != 0 ? indent(level, current) : "") << '}'; + break; + } + case Type::Real: + oss << m_number; + break; + case Type::String: + oss << "\"" << escape(m_string) << "\""; + break; + default: + break; + } + + return oss.str(); +} + std::string escape(const std::string &value) { std::string result;
--- a/C++/modules/Json/Json.h Thu Nov 12 08:57:21 2015 +0100 +++ b/C++/modules/Json/Json.h Thu Nov 12 11:46:04 2015 +0100 @@ -184,6 +184,7 @@ void copy(const Value &); void move(Value &&); + std::string toJson(int indent, int current) const; /** * @class BaseIterator @@ -344,6 +345,7 @@ } }; +public: /** * Forward iterator. */ @@ -354,7 +356,6 @@ */ using const_iterator = BaseIterator<const Value, typename std::deque<Value>::const_iterator, typename std::map<std::string, Value>::const_iterator>; -public: /** * Construct a null value. */ @@ -1111,6 +1112,18 @@ m_object.erase(key); } + + /** + * Return this value as JSon representation. + * + * @param indent, the indentation to use (0 == compact, < 0 == tabs, > 0 == number of spaces) + * @param tabs, use tabs or not + * @return the string + */ + inline std::string toJson(int indent = 2) const + { + return toJson(indent, 0); + } }; /**
--- a/C++/tests/Json/main.cpp Thu Nov 12 08:57:21 2015 +0100 +++ b/C++/tests/Json/main.cpp Thu Nov 12 11:46:04 2015 +0100 @@ -780,6 +780,86 @@ } } +/* + * Value::toJson + * ------------------------------------------------------------------ + */ + +TEST(ToJsonCompact, simpleObject) +{ + json::Value v = json::object({ { "x", 10 }, { "y", 20 } }); + std::string result = v.toJson(0); + std::string expected = "{\"x\":10,\"y\":20}"; + + ASSERT_EQ(expected, result); +} + +TEST(ToJsonCompact, deepObject) +{ + json::Value v = json::object({ + { "x", 10 }, + { "y", 20 }, + { "network", json::object({ + { "host", "localhost" } + })} + }); + + std::string result = v.toJson(0); + std::string expected = "{\"network\":{\"host\":\"localhost\"},\"x\":10,\"y\":20}"; + + ASSERT_EQ(expected, result); +} + +TEST(ToJsonCompact, simpleArray) +{ + json::Value v = json::array({ 1, 2, 3 }); + std::string result = v.toJson(0); + std::string expected = "[1,2,3]"; + + ASSERT_EQ(expected, result); +} + +TEST(ToJsonCompact, deepArray) +{ + json::Value v = json::array({ + 1, + 2, + json::array({ 4, 5, 6 }) + }); + std::string result = v.toJson(0); + std::string expected = "[1,2,[4,5,6]]"; + + ASSERT_EQ(expected, result); +} + +TEST(ToJsonIndentSpaces, object) +{ + json::Value v = json::object({ + { "x", 10 }, + { "y", 20 }, + { "network", json::object({ + { "host", "localhost" } + })} + }); + std::string result = v.toJson(2); + std::string expected = "{\n \"network\": {\n \"host\": \"localhost\"\n },\n \"x\": 10,\n \"y\": 20\n}"; + + ASSERT_EQ(expected, result); +} + +TEST(ToJsonIndentSpaces, array) +{ + json::Value v = json::array({ + 1, + 2, + json::object({ { "x", 10 } }) + }); + std::string result = v.toJson(); + std::string expected = "[\n 1,\n 2,\n {\n \"x\": 10\n }\n]"; + + ASSERT_EQ(expected, result); +} + int main(int argc, char **argv) { testing::InitGoogleTest(&argc, argv);