From 76775ddf26451b729a0039e791b08e1faf7256d3 Mon Sep 17 00:00:00 2001 From: Vladimir Krivopalov Date: Mon, 4 Dec 2017 21:03:05 -0800 Subject: [PATCH] Use CharReaderBuilder/CharReader and StreamWriterBuilder from JsonCpp. In version 1.8.3 of JsonCpp shipped with Fedora 27, old FastWriter and Reader classes from JsonCpp have been deprecated in favour of newer/better ones: CharReaderBuilder/CharReader and StreamWriterBuilder/StreamWriter. This fix uses the new classes where available or resorts to old ones for older versions of the library. Fixes #2989 Signed-off-by: Vladimir Krivopalov --- json.hh | 47 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/json.hh b/json.hh index 92d2a2028d..0a903ec7c2 100644 --- a/json.hh +++ b/json.hh @@ -22,34 +22,59 @@ #pragma once #include "core/sstring.hh" +#include "core/print.hh" #include namespace seastar { // FIXME: not ours namespace json { +inline sstring to_sstring(const Json::Value& value) { +#if defined(JSONCPP_VERSION_HEXA) && (JSONCPP_VERSION_HEXA >= 0x010400) // >= 1.4.0 + Json::StreamWriterBuilder wbuilder; + wbuilder.settings_["indentation"] = ""; + auto str = Json::writeString(wbuilder, value); +#else + Json::FastWriter writer; + // Json::FastWriter unnecessarily adds a newline at the end of string. + // There is a method omitEndingLineFeed() which prevents that, but it seems + // to be too recent addition, so, at least for now, a workaround is needed. + auto str = writer.write(value); + if (str.length() && str.back() == '\n') { + str.pop_back(); + } +#endif + return str; +} + template inline sstring to_json(const Map& map) { Json::Value root(Json::objectValue); for (auto&& kv : map) { root[kv.first] = Json::Value(kv.second); } - Json::FastWriter writer; - // Json::FastWriter unnecessarily adds a newline at the end of string. - // There is a method omitEndingLineFeed() which prevents that, but it seems - // to be too recent addition, so, at least for now, a workaround is needed. - auto str = writer.write(root); - if (str.length() && str.back() == '\n') { - str.pop_back(); + return to_sstring(root); +} + +inline Json::Value to_json_value(const sstring& raw) { + Json::Value root; +#if defined(JSONCPP_VERSION_HEXA) && (JSONCPP_VERSION_HEXA >= 0x010400) // >= 1.4.0 + Json::CharReaderBuilder rbuilder; + std::unique_ptr reader(rbuilder.newCharReader()); + bool result = reader->parse(raw.begin(), raw.end(), &root, NULL); + if (!result) { + throw std::runtime_error(sprint("Failed to parse JSON: %s", raw)); } - return str; +#else + Json::Reader reader; + reader.parse(std::string{raw}, root); +#endif + return root; } template inline Map to_map(const sstring& raw, Map&& map) { - Json::Value root; - Json::Reader reader; - reader.parse(std::string{raw}, root); + Json::Value root = to_json_value(raw); for (auto&& member : root.getMemberNames()) { map.emplace(member, root[member].asString()); }