Commit e40b753b authored by Dominik Charousset's avatar Dominik Charousset

Compress empty JSON arrays and objects

parent 8e2a5aa1
...@@ -25,6 +25,13 @@ constexpr const char* json_type_name(json_writer::type t) { ...@@ -25,6 +25,13 @@ constexpr const char* json_type_name(json_writer::type t) {
return json_type_names[static_cast<uint8_t>(t)]; return json_type_names[static_cast<uint8_t>(t)];
} }
char last_non_ws_char(const std::vector<char>& buf) {
auto not_ws = [](char c) { return !std::isspace(c); };
auto last = buf.rend();
auto i = std::find_if(buf.rbegin(), last, not_ws);
return (i != last) ? *i : '\0';
}
} // namespace } // namespace
// -- implementation details --------------------------------------------------- // -- implementation details ---------------------------------------------------
...@@ -247,7 +254,13 @@ bool json_writer::begin_sequence(size_t) { ...@@ -247,7 +254,13 @@ bool json_writer::begin_sequence(size_t) {
bool json_writer::end_sequence() { bool json_writer::end_sequence() {
if (pop_if(type::array)) { if (pop_if(type::array)) {
--indentation_level_; --indentation_level_;
// Check whether the array was empty and compress the output in that case.
if (last_non_ws_char(buf_) == '[') {
while (std::isspace(buf_.back()))
buf_.pop_back();
} else {
nl(); nl();
}
add(']'); add(']');
return true; return true;
} else { } else {
...@@ -278,7 +291,13 @@ bool json_writer::begin_associative_array(size_t) { ...@@ -278,7 +291,13 @@ bool json_writer::begin_associative_array(size_t) {
bool json_writer::end_associative_array() { bool json_writer::end_associative_array() {
if (pop_if(type::object)) { if (pop_if(type::object)) {
--indentation_level_; --indentation_level_;
// Check whether the array was empty and compress the output in that case.
if (last_non_ws_char(buf_) == '{') {
while (std::isspace(buf_.back()))
buf_.pop_back();
} else {
nl(); nl();
}
add('}'); add('}');
if (!stack_.empty()) if (!stack_.empty())
stack_.back().filled = true; stack_.back().filled = true;
......
...@@ -314,4 +314,33 @@ SCENARIO("the JSON writer annotates variant fields") { ...@@ -314,4 +314,33 @@ SCENARIO("the JSON writer annotates variant fields") {
} }
} }
SCENARIO("the JSON compresses empty lists and objects") {
GIVEN("a map with an empty list value") {
std::map<std::string, std::vector<int>> obj;
obj["xs"] = std::vector<int>{};
obj["ys"] = std::vector<int>{1, 2, 3};
WHEN("converting it to JSON with indentation factor 2") {
THEN("the JSON contains a compressed representation of the empty list") {
std::string out = R"({
"xs": [],
"ys": [
1,
2,
3
]
})";
CHECK_EQ(to_json_string(obj, 2, true, true), out);
}
}
}
GIVEN("an empty map") {
std::map<std::string, std::vector<int>> obj;
WHEN("converting it to JSON with indentation factor 2") {
THEN("the JSON contains a compressed representation of the empty map") {
CHECK_EQ(to_json_string(obj, 2, true, true), "{}"s);
}
}
}
}
END_FIXTURE_SCOPE() END_FIXTURE_SCOPE()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment