Permalink
Browse files

json: Allow formatting read json back to writer.

  • Loading branch information...
unknownbrackets committed Apr 14, 2018
1 parent fb876e7 commit 03cc4eab0170befe52f220f0efe4f1c9b097c2d5
Showing with 152 additions and 2 deletions.
  1. +134 −0 ext/native/json/json_writer.cpp
  2. +18 −2 ext/native/json/json_writer.h
@@ -1,5 +1,6 @@
#include <iomanip>
#include <cstring>
#include "ext/vjson/json.h"
#include "json/json_writer.h"
JsonWriter::JsonWriter(int flags) {
@@ -15,6 +16,16 @@ void JsonWriter::begin() {
stack_.push_back(StackEntry(DICT));
}
void JsonWriter::beginArray() {
str_ << "[";
stack_.push_back(StackEntry(ARRAY));
}
void JsonWriter::beginRaw() {
// For the uncommon case of writing a value directly, to avoid duplicated code.
stack_.push_back(StackEntry(RAW));
}
void JsonWriter::end() {
pop();
if (pretty_)
@@ -41,6 +52,8 @@ const char *JsonWriter::indent() const {
}
const char *JsonWriter::arrayIndent() const {
if (!pretty_)
return "";
int amount = (int)stack_.size() + 1;
amount *= 2; // 2-space indent.
return stack_.back().first ? indent(amount) : "";
@@ -128,6 +141,19 @@ void JsonWriter::writeString(const char *name, const char *value) {
stack_.back().first = false;
}
void JsonWriter::writeRaw(const char *value) {
str_ << arrayComma() << arrayIndent() << value;
stack_.back().first = false;
}
void JsonWriter::writeRaw(const char *name, const char *value) {
str_ << comma() << indent() << "\"";
writeEscapedString(name);
str_ << (pretty_ ? "\": " : "\":");
str_ << value;
stack_.back().first = false;
}
void JsonWriter::pop() {
BlockType type = stack_.back().type;
stack_.pop_back();
@@ -140,6 +166,8 @@ void JsonWriter::pop() {
case DICT:
str_ << "}";
break;
case RAW:
break;
}
if (stack_.size() > 0)
stack_.back().first = false;
@@ -181,3 +209,109 @@ void JsonWriter::writeEscapedString(const char *str) {
str_ << str;
}
}
static void json_stringify_object(JsonWriter &writer, const json_value *value);
static void json_stringify_array(JsonWriter &writer, const json_value *value);
std::string json_stringify(const json_value *value) {
JsonWriter writer;
// Handle direct values too, not just objects.
switch (value->type) {
case JSON_NULL:
case JSON_STRING:
case JSON_INT:
case JSON_FLOAT:
case JSON_BOOL:
writer.beginRaw();
// It's the same as a one entry array without brackets, so reuse.
json_stringify_array(writer, value);
break;
case JSON_OBJECT:
writer.begin();
for (const json_value *it = value->first_child; it; it = it->next_sibling) {
json_stringify_object(writer, it);
}
break;
case JSON_ARRAY:
writer.beginArray();
for (const json_value *it = value->first_child; it; it = it->next_sibling) {
json_stringify_array(writer, it);
}
break;
}
writer.end();
return writer.str();
}
static void json_stringify_object(JsonWriter &writer, const json_value *value) {
switch (value->type) {
case JSON_NULL:
writer.writeRaw(value->name, "null");
break;
case JSON_STRING:
writer.writeString(value->name, value->string_value);
break;
case JSON_INT:
writer.writeInt(value->name, value->int_value);
break;
case JSON_FLOAT:
writer.writeFloat(value->name, value->float_value);
break;
case JSON_BOOL:
writer.writeBool(value->name, value->int_value != 0);
break;
case JSON_OBJECT:
writer.pushDict(value->name);
for (const json_value *it = value->first_child; it; it = it->next_sibling) {
json_stringify_object(writer, it);
}
writer.pop();
break;
case JSON_ARRAY:
writer.pushArray(value->name);
for (const json_value *it = value->first_child; it; it = it->next_sibling) {
json_stringify_array(writer, it);
}
writer.pop();
break;
}
}
static void json_stringify_array(JsonWriter &writer, const json_value *value) {
switch (value->type) {
case JSON_NULL:
writer.writeRaw("null");
break;
case JSON_STRING:
writer.writeString(value->string_value);
break;
case JSON_INT:
writer.writeInt(value->int_value);
break;
case JSON_FLOAT:
writer.writeFloat(value->float_value);
break;
case JSON_BOOL:
writer.writeBool(value->int_value != 0);
break;
case JSON_OBJECT:
writer.begin();
for (const json_value *it = value->first_child; it; it = it->next_sibling) {
json_stringify_object(writer, it);
}
writer.pop();
break;
case JSON_ARRAY:
writer.beginArray();
for (const json_value *it = value->first_child; it; it = it->next_sibling) {
json_stringify_array(writer, it);
}
writer.pop();
break;
}
}
@@ -7,8 +7,7 @@
//
// Does not deal with encodings in any way.
//
// Zero dependencies apart from stdlib.
// See json_writer_test.cpp for usage.
// Zero dependencies apart from stdlib (if you remove the vhjson usage.)
#include <string>
#include <vector>
@@ -19,6 +18,8 @@ class JsonWriter {
JsonWriter(int flags = NORMAL);
~JsonWriter();
void begin();
void beginArray();
void beginRaw();
void end();
void pushDict(const char *name);
void pushArray(const char *name);
@@ -40,6 +41,17 @@ class JsonWriter {
void writeString(const std::string &name, const std::string &value) {
writeString(name.c_str(), value.c_str());
}
void writeRaw(const char *value);
void writeRaw(const char *name, const char *value);
void writeRaw(const std::string &value) {
writeRaw(value.c_str());
}
void writeRaw(const char *name, const std::string &value) {
writeRaw(name, value.c_str());
}
void writeRaw(const std::string &name, const std::string &value) {
writeRaw(name.c_str(), value.c_str());
}
std::string str() const {
return str_.str();
@@ -61,6 +73,7 @@ class JsonWriter {
enum BlockType {
ARRAY,
DICT,
RAW,
};
struct StackEntry {
StackEntry(BlockType t) : type(t), first(true) {}
@@ -71,3 +84,6 @@ class JsonWriter {
std::ostringstream str_;
bool pretty_;
};
struct json_value;
std::string json_stringify(const json_value *json);

0 comments on commit 03cc4ea

Please sign in to comment.