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 <vladimir@scylladb.com>
This commit is contained in:
Vladimir Krivopalov
2017-12-04 21:03:05 -08:00
parent 114c71dcd8
commit 76775ddf26

47
json.hh
View File

@@ -22,34 +22,59 @@
#pragma once
#include "core/sstring.hh"
#include "core/print.hh"
#include <json/json.h>
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<typename Map>
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<Json::CharReader> 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<typename Map>
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());
}