Util: Add a JSON stringifier
This commit is contained in:
@@ -0,0 +1,140 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 Riyyi
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstdint> // uint32_t
|
||||||
|
#include <iterator> // prev
|
||||||
|
#include <sstream> // ostringstream
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "util/json/array.h"
|
||||||
|
#include "util/json/lexer.h"
|
||||||
|
#include "util/json/object.h"
|
||||||
|
#include "util/json/stringify.h"
|
||||||
|
|
||||||
|
namespace Json {
|
||||||
|
|
||||||
|
Stringify::Stringify(const Value& value, const uint32_t indent, const char indentCharacter)
|
||||||
|
: m_value(value)
|
||||||
|
, m_indent(indent)
|
||||||
|
, m_indentCharacter(indentCharacter)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Stringify::~Stringify()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------
|
||||||
|
|
||||||
|
std::string Stringify::dump()
|
||||||
|
{
|
||||||
|
return dumpHelper(m_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------
|
||||||
|
|
||||||
|
std::string Stringify::dumpHelper(const Value& value, const uint32_t indentLevel)
|
||||||
|
{
|
||||||
|
switch (value.type()) {
|
||||||
|
case Value::Type::Null:
|
||||||
|
return "null";
|
||||||
|
break;
|
||||||
|
case Value::Type::Bool:
|
||||||
|
return value.asBool() ? "true" : "false";
|
||||||
|
break;
|
||||||
|
case Value::Type::Number: {
|
||||||
|
std::ostringstream os;
|
||||||
|
os << value.asDouble();
|
||||||
|
return os.str();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Value::Type::String:
|
||||||
|
return "\"" + value.asString() + "\"";
|
||||||
|
break;
|
||||||
|
case Value::Type::Array:
|
||||||
|
return dumpArray(value, indentLevel);
|
||||||
|
break;
|
||||||
|
case Value::Type::Object:
|
||||||
|
return dumpObject(value, indentLevel);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Stringify::dumpArray(const Value& value, const uint32_t indentLevel)
|
||||||
|
{
|
||||||
|
std::string result;
|
||||||
|
|
||||||
|
// Append [
|
||||||
|
result += "[";
|
||||||
|
if (m_indent > 0) {
|
||||||
|
result += '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
auto values = value.asArray().values();
|
||||||
|
for (auto it = values.begin(); it != values.end(); ++it) {
|
||||||
|
result += std::string(m_indent * (indentLevel + 1), m_indentCharacter);
|
||||||
|
result += dumpHelper(*it, indentLevel + 1);
|
||||||
|
|
||||||
|
// Add comma, except after the last element
|
||||||
|
if (it != std::prev(values.end(), 1)) {
|
||||||
|
result += ",";
|
||||||
|
}
|
||||||
|
if (m_indent > 0) {
|
||||||
|
result += '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append indentation
|
||||||
|
result += std::string(m_indent * indentLevel, m_indentCharacter);
|
||||||
|
|
||||||
|
// Append ]
|
||||||
|
result += "]";
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Stringify::dumpObject(const Value& value, const uint32_t indentLevel)
|
||||||
|
{
|
||||||
|
std::string result;
|
||||||
|
|
||||||
|
// Append {
|
||||||
|
result += "{";
|
||||||
|
if (m_indent > 0) {
|
||||||
|
result += '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
auto members = value.asObject().members();
|
||||||
|
for (auto it = members.begin(); it != members.end(); ++it) {
|
||||||
|
result += std::string(m_indent * (indentLevel + 1), m_indentCharacter);
|
||||||
|
result += "\"" + it->first + "\":";
|
||||||
|
if (m_indent > 0) {
|
||||||
|
result += ' ';
|
||||||
|
}
|
||||||
|
result += dumpHelper(it->second, indentLevel + 1);
|
||||||
|
|
||||||
|
// Add comma, except after the last element
|
||||||
|
if (it != std::prev(members.end(), 1)) {
|
||||||
|
result += ",";
|
||||||
|
}
|
||||||
|
if (m_indent > 0) {
|
||||||
|
result += '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append indentation
|
||||||
|
result += std::string(m_indent * indentLevel, m_indentCharacter);
|
||||||
|
|
||||||
|
// Append }
|
||||||
|
result += "}";
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Json
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 Riyyi
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef JSON_STRINGIFY_H
|
||||||
|
#define JSON_STRINGIFY_H
|
||||||
|
|
||||||
|
#include <cstdint> // uint32_t
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "util/json/value.h"
|
||||||
|
|
||||||
|
namespace Json {
|
||||||
|
|
||||||
|
class Stringify {
|
||||||
|
public:
|
||||||
|
Stringify(const Value& value, const uint32_t indent = 0, const char indentCharacter = ' ');
|
||||||
|
virtual ~Stringify();
|
||||||
|
|
||||||
|
std::string dump();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string dumpHelper(const Value& value, const uint32_t indentLevel = 0);
|
||||||
|
std::string dumpArray(const Value& value, const uint32_t indentLevel = 0);
|
||||||
|
std::string dumpObject(const Value& value, const uint32_t indentLevel = 0);
|
||||||
|
|
||||||
|
Value m_value;
|
||||||
|
|
||||||
|
uint32_t m_indent { 0 };
|
||||||
|
char m_indentCharacter { ' ' };
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Json
|
||||||
|
|
||||||
|
#endif // JSON_STRINGIFY_H
|
||||||
@@ -44,6 +44,8 @@ public:
|
|||||||
Value operator[](size_t index);
|
Value operator[](size_t index);
|
||||||
Value operator[](const std::string& key);
|
Value operator[](const std::string& key);
|
||||||
|
|
||||||
|
Type type() const { return m_type; }
|
||||||
|
|
||||||
bool asBool() const { return m_value.asBool; }
|
bool asBool() const { return m_value.asBool; }
|
||||||
double asDouble() const { return m_value.asDouble; }
|
double asDouble() const { return m_value.asDouble; }
|
||||||
const std::string& asString() const { return *m_value.asString; }
|
const std::string& asString() const { return *m_value.asString; }
|
||||||
|
|||||||
Reference in New Issue
Block a user