From 2b7a9a896c9bfc1d60f1dcf166f40077a83a1e5d Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Fri, 15 Nov 2019 18:32:17 -0800 Subject: [PATCH] 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 --- src/common/Formatter.h | 4 +++ src/common/ceph_json.h | 55 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 58 insertions(+), 1 deletion(-) 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); -- 2.39.5