From 6ae103dd63e6096818f8ebb7e7d05ad48425a98f Mon Sep 17 00:00:00 2001 From: Henning Koehler Date: Thu, 14 Sep 2017 13:03:44 +1200 Subject: [PATCH] print json in compact format --- config/heroes/castle.json | 17 ++++------------ lib/CHeroHandler.cpp | 8 ++++---- lib/JsonDetail.cpp | 41 ++++++++++++++++++++++++++------------- lib/JsonDetail.h | 6 +++++- lib/JsonNode.cpp | 33 +++++++++++++++++++++++++++---- lib/JsonNode.h | 3 ++- 6 files changed, 71 insertions(+), 37 deletions(-) diff --git a/config/heroes/castle.json b/config/heroes/castle.json index 68fcd3297..eef22ab0a 100644 --- a/config/heroes/castle.json +++ b/config/heroes/castle.json @@ -17,7 +17,7 @@ "valueType" : "PERCENT_TO_BASE", "updater" : { "type" : "GROWS_WITH_LEVEL", - "parameters" : [100] + "parameters" : [ 100 ] } } } @@ -36,10 +36,7 @@ "specialty" : { "base" : { "limiter" : { - "parameters" : [ - "archer", - true - ], + "parameters" : [ "archer", true ], "type" : "CREATURE_TYPE_LIMITER" } }, @@ -48,10 +45,7 @@ "subtype" : "primSkill.attack", "type" : "PRIMARY_SKILL", "updater" : { - "parameters" : [ - 6, - 2 - ], + "parameters" : [ 6, 2 ], "type" : "GROWS_WITH_LEVEL" } }, @@ -59,10 +53,7 @@ "subtype" : "primSkill.defence", "type" : "PRIMARY_SKILL", "updater" : { - "parameters" : [ - 3, - 2 - ], + "parameters" : [ 3, 2 ], "type" : "GROWS_WITH_LEVEL" } }, diff --git a/lib/CHeroHandler.cpp b/lib/CHeroHandler.cpp index c058bc9f8..316d05eff 100644 --- a/lib/CHeroHandler.cpp +++ b/lib/CHeroHandler.cpp @@ -537,7 +537,7 @@ void CHeroHandler::beforeValidate(JsonNode & object) { //handle "base" specialty info const JsonNode & specialtyNode = object["specialty"]; - if(specialtyNode.getType() == JsonNode::DATA_STRUCT) + if(specialtyNode.getType() == JsonNode::JsonType::DATA_STRUCT) { const JsonNode & base = specialtyNode["base"]; if(!base.isNull()) @@ -577,7 +577,7 @@ void CHeroHandler::loadHeroSpecialty(CHero * hero, const JsonNode & node) } //new(er) format, using bonus system const JsonNode & specialtyNode = node["specialty"]; - if(specialtyNode.getType() == JsonNode::DATA_VECTOR) + if(specialtyNode.getType() == JsonNode::JsonType::DATA_VECTOR) { //deprecated middle-aged format for(const JsonNode & specialty : node["specialty"].Vector()) @@ -586,7 +586,7 @@ void CHeroHandler::loadHeroSpecialty(CHero * hero, const JsonNode & node) hero->specialty.push_back(prepSpec(JsonUtils::parseBonus(bonus))); } } - else if(specialtyNode.getType() == JsonNode::DATA_STRUCT) + else if(specialtyNode.getType() == JsonNode::JsonType::DATA_STRUCT) { //proper new format for(auto keyValue : specialtyNode["bonuses"].Struct()) @@ -792,7 +792,7 @@ void CHeroHandler::afterLoadFinalization() specNode["bonuses"].Struct(); for(int i = 0; i < specVec.size(); i++) specNode["bonuses"][specNames[i]] = specVec[i]; - logMod->trace("\"specialty\" : %s", specNode.toJson()); + logMod->trace("\"specialty\" : %s", specNode.toJson(true)); } } } diff --git a/lib/JsonDetail.cpp b/lib/JsonDetail.cpp index c16276c76..f5a7503d1 100644 --- a/lib/JsonDetail.cpp +++ b/lib/JsonDetail.cpp @@ -32,19 +32,22 @@ void JsonWriter::writeContainer(Iterator begin, Iterator end) while (begin != end) { - out<<",\n"; + out << (compactMode ? ", " : ",\n"); writeEntry(begin++); } - out<<"\n"; + out << (compactMode ? "" : "\n"); prefix.resize(prefix.size()-1); } void JsonWriter::writeEntry(JsonMap::const_iterator entry) { - if (!entry->second.meta.empty()) - out << prefix << " // " << entry->second.meta << "\n"; - out << prefix; + if(!compactMode) + { + if (!entry->second.meta.empty()) + out << prefix << " // " << entry->second.meta << "\n"; + out << prefix; + } writeString(entry->first); out << " : "; writeNode(entry->second); @@ -52,9 +55,12 @@ void JsonWriter::writeEntry(JsonMap::const_iterator entry) void JsonWriter::writeEntry(JsonVector::const_iterator entry) { - if (!entry->meta.empty()) - out << prefix << " // " << entry->meta << "\n"; - out << prefix; + if(!compactMode) + { + if (!entry->meta.empty()) + out << prefix << " // " << entry->meta << "\n"; + out << prefix; + } writeNode(*entry); } @@ -94,6 +100,10 @@ void JsonWriter::writeString(const std::string &string) void JsonWriter::writeNode(const JsonNode &node) { + bool originalMode = compactMode; + if(compact && !compactMode && node.isCompact()) + compactMode = true; + switch(node.getType()) { break; case JsonNode::JsonType::DATA_NULL: @@ -112,21 +122,24 @@ void JsonWriter::writeNode(const JsonNode &node) writeString(node.String()); break; case JsonNode::JsonType::DATA_VECTOR: - out << "[" << "\n"; + out << "[" << (compactMode ? " " : "\n"); writeContainer(node.Vector().begin(), node.Vector().end()); - out << prefix << "]"; + out << (compactMode ? " " : prefix) << "]"; break; case JsonNode::JsonType::DATA_STRUCT: - out << "{" << "\n"; + out << "{" << (compactMode ? " " : "\n"); writeContainer(node.Struct().begin(), node.Struct().end()); - out << prefix << "}"; + out << (compactMode ? " " : prefix) << "}"; + break; case JsonNode::JsonType::DATA_INTEGER: out << node.Integer(); } + + compactMode = originalMode; } -JsonWriter::JsonWriter(std::ostream & output) - : out(output) +JsonWriter::JsonWriter(std::ostream & output, bool compact) + : out(output), compact(compact) { } diff --git a/lib/JsonDetail.h b/lib/JsonDetail.h index 49fcb4e2b..5095eabd9 100644 --- a/lib/JsonDetail.h +++ b/lib/JsonDetail.h @@ -16,6 +16,10 @@ class JsonWriter //prefix for each line (tabulation) std::string prefix; std::ostream & out; + //sets whether compact nodes are written in single-line format + bool compact; + //tracks whether we are currently using single-line format + bool compactMode = false; public: template void writeContainer(Iterator begin, Iterator end); @@ -23,7 +27,7 @@ public: void writeEntry(JsonVector::const_iterator entry); void writeString(const std::string & string); void writeNode(const JsonNode & node); - JsonWriter(std::ostream & output); + JsonWriter(std::ostream & output, bool compact = false); }; //Tiny string class that uses const char* as data for speed, members are private diff --git a/lib/JsonNode.cpp b/lib/JsonNode.cpp index 0a17892f1..1c6d32a8e 100644 --- a/lib/JsonNode.cpp +++ b/lib/JsonNode.cpp @@ -232,6 +232,31 @@ bool JsonNode::isEmpty() const } } +bool JsonNode::isCompact() const +{ + switch(type) + { + case JsonType::DATA_VECTOR: + for(JsonNode & elem : *data.Vector) + { + if(!elem.isCompact()) + return false; + } + return true; + case JsonType::DATA_STRUCT: + { + int propertyCount = data.Struct->size(); + if(propertyCount == 0) + return true; + else if(propertyCount == 1) + return data.Struct->begin()->second.isCompact(); + } + return false; + default: + return true; + } +} + void JsonNode::clear() { setType(JsonType::DATA_NULL); @@ -385,10 +410,10 @@ JsonNode & JsonNode::resolvePointer(const std::string &jsonPointer) return ::resolvePointer(*this, jsonPointer); } -std::string JsonNode::toJson() const +std::string JsonNode::toJson(bool compact) const { std::ostringstream out; - JsonWriter writer(out); + JsonWriter writer(out, compact); writer.writeNode(*this); out << "\n"; return out.str(); @@ -901,10 +926,10 @@ JsonNode JsonUtils::intersect(const JsonNode & a, const JsonNode & b, bool prune JsonNode JsonUtils::difference(const JsonNode & node, const JsonNode & base) { - if(node.getType() == JsonNode::DATA_STRUCT && base.getType() == JsonNode::DATA_STRUCT) + if(node.getType() == JsonNode::JsonType::DATA_STRUCT && base.getType() == JsonNode::JsonType::DATA_STRUCT) { // subtract individual properties - JsonNode result(JsonNode::DATA_STRUCT); + JsonNode result(JsonNode::JsonType::DATA_STRUCT); for(auto property : node.Struct()) { if(vstd::contains(base.Struct(), property.first)) diff --git a/lib/JsonNode.h b/lib/JsonNode.h index a6d666c88..1d7e1c76e 100644 --- a/lib/JsonNode.h +++ b/lib/JsonNode.h @@ -76,6 +76,7 @@ public: bool isNull() const; bool isNumber() const; bool isEmpty() const; + bool isCompact() const; /// removes all data from node and sets type to null void clear(); @@ -111,7 +112,7 @@ public: JsonNode & operator[](std::string child); const JsonNode & operator[](std::string child) const; - std::string toJson() const; + std::string toJson(bool compact = false) const; template void serialize(Handler &h, const int version) {