From: Yehuda Sadeh Date: Sat, 16 Nov 2019 02:32:17 +0000 (-0800) Subject: ceph_json: json encoding filter X-Git-Tag: v15.1.0~22^2~57 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=2b7a9a896c9bfc1d60f1dcf166f40077a83a1e5d;p=ceph-ci.git ceph_json: json encoding filter Can create and register a filter (that will be pointed at by the formatter as an external feature), that could be then used to replace default encoders for specific data types. This can be useful in cases where we want to mutate the output (for example: translate zone ids to zone names on the fly). Signed-off-by: Yehuda Sadeh --- diff --git a/src/common/Formatter.h b/src/common/Formatter.h index c4cdd552373..d2a1d55c480 100644 --- a/src/common/Formatter.h +++ b/src/common/Formatter.h @@ -114,6 +114,10 @@ namespace ceph { { dump_string(name, s); } + + virtual void *get_external_feature_handler(const std::string& feature) { + return nullptr; + } }; class copyable_sstream : public std::stringstream { diff --git a/src/common/ceph_json.h b/src/common/ceph_json.h index 27d2dddd139..207babc1f15 100644 --- a/src/common/ceph_json.h +++ b/src/common/ceph_json.h @@ -2,6 +2,7 @@ #define CEPH_JSON_H #include +#include #include #include @@ -411,14 +412,66 @@ bool JSONDecoder::decode_json(const char *name, std::optional& val, JSONObj * return true; } +class JSONEncodeFilter +{ +public: + class HandlerBase { + public: + virtual ~HandlerBase() {} + + virtual std::type_index get_type() = 0; + virtual void encode_json(const char *name, const void *pval, ceph::Formatter *) const = 0; + }; + + template + class Handler : public HandlerBase { + public: + virtual ~Handler() {} + + std::type_index get_type() override { + return std::type_index(typeid(const T&)); + } + }; + +private: + std::map handlers; + +public: + void register_type(HandlerBase *h) { + handlers[h->get_type()] = h; + } + + template + bool encode_json(const char *name, const T& val, ceph::Formatter *f) { + auto iter = handlers.find(std::type_index(typeid(val))); + if (iter == handlers.end()) { + return false; + } + + iter->second->encode_json(name, (const void *)&val, f); + return true; + } +}; + template -static void encode_json(const char *name, const T& val, ceph::Formatter *f) +static void encode_json_impl(const char *name, const T& val, ceph::Formatter *f) { f->open_object_section(name); val.dump(f); f->close_section(); } +template +static void encode_json(const char *name, const T& val, ceph::Formatter *f) +{ + JSONEncodeFilter *filter = static_cast(f->get_external_feature_handler("JSONEncodeFilter")); + + if (!filter || + !filter->encode_json(name, val, f)) { + encode_json_impl(name, val, f); + } +} + class utime_t; void encode_json(const char *name, const std::string& val, ceph::Formatter *f);