YPC  0.2.0
ntjson.h
1 #pragma once
2 #include <boost/property_tree/json_parser.hpp>
3 #include <boost/property_tree/ptree.hpp>
4 #include <ff/util/ntobject.h>
5 #include <glog/logging.h>
6 
7 namespace ypc {
8 template <typename CT> struct user_def_name {};
9 
10 namespace internal {
11 
12 template <typename T, typename = int> struct has_name : std::false_type {};
13 template <typename T>
14 struct has_name<T, decltype((void)T::name, 0)> : std::true_type {};
15 
16 template <typename CT,
17  bool is_user_def = internal::has_name<user_def_name<CT>>::value>
18 struct name_traits {
19  constexpr static const char *name = user_def_name<CT>::name;
20 };
21 template <typename CT> struct name_traits<CT, false> {
22  constexpr static const char *name = ff::util::internal::nt_traits<CT>::name;
23 };
24 
25 template <typename CType,
26  typename UnderlyingType =
27  typename ff::util::internal::nt_traits<CType>::type>
29  template <typename NtObjTy>
30  static void write(boost::property_tree::ptree &pt, const NtObjTy &data) {
31  pt.put(name_traits<CType>::name, data.template get<CType>());
32  }
33 };
34 template <typename CType,
35  typename UnderlyingType =
36  typename ff::util::internal::nt_traits<CType>::type>
38  template <typename NtObjTy>
39  static void read(const boost::property_tree::ptree &pt, NtObjTy &data) {
40  if (pt.find(name_traits<CType>::name) != pt.not_found()) {
41  data.template set<CType>(
42  pt.get<UnderlyingType>(name_traits<CType>::name));
43  } else {
44  LOG(WARNING) << "cannot find json item with name: "
46  << ", use default value: " << UnderlyingType();
47  }
48  }
49 };
50 template <typename T> struct to_ptree {
51  static boost::property_tree::ptree f(const T &value) {
52  boost::property_tree::ptree child(std::to_string(value));
53  return child;
54  }
55 };
56 
57 template <typename T> struct from_ptree {
58  static T f(const boost::property_tree::ptree &ptree) {
59  std::stringstream ss;
60  ss << ptree.data();
61  T t;
62  ss >> t;
63  return t;
64  }
65 };
66 
67 template <typename CType, typename T>
68 struct ptree_put_helper<CType, std::vector<T>> {
69  template <typename NtObjTy>
70  static void write(boost::property_tree::ptree &pt, const NtObjTy &data) {
71  boost::property_tree::ptree ptree;
72  const std::vector<T> &vec = data.template get<CType>();
73  for (auto item : vec) {
74  boost::property_tree::ptree child = to_ptree<T>::f(item);
75  ptree.push_back(std::make_pair("", child));
76  }
77  pt.add_child(name_traits<CType>::name, std::move(ptree));
78  }
79 };
80 
81 template <typename CType, typename... ARGS>
82 struct ptree_put_helper<CType, ff::util::ntobject<ARGS...>> {
83  template <typename NtObjTy>
84  static void write(boost::property_tree::ptree &pt, const NtObjTy &data) {
85  boost::property_tree::ptree ptree =
86  to_ptree<ff::util::ntobject<ARGS...>>::f(data.template get<CType>());
87  pt.add_child(name_traits<CType>::name, std::move(ptree));
88  }
89 };
90 
91 template <typename CType, typename T>
92 struct ptree_get_helper<CType, std::vector<T>> {
93  template <typename NtObjTy>
94  static void read(const boost::property_tree::ptree &pt, NtObjTy &data) {
95  if (pt.find(name_traits<CType>::name) == pt.not_found()) {
96  LOG(WARNING) << "cannot find json item with name: "
97  << name_traits<CType>::name << ", use default empty vector.";
98  return;
99  }
100  std::vector<T> d;
101  auto ptree = pt.get_child(name_traits<CType>::name);
102  for (auto it = ptree.begin(); it != ptree.end(); ++it) {
103  d.push_back(from_ptree<T>::f(it->second));
104  }
105 
106  data.template set<CType>(std::move(d));
107  }
108 };
109 template <typename CType, typename... ARGS>
110 struct ptree_get_helper<CType, ff::util::ntobject<ARGS...>> {
111  template <typename NtObjTy>
112  static void read(const boost::property_tree::ptree &pt, NtObjTy &data) {
113  if (pt.find(name_traits<CType>::name) == pt.not_found()) {
114  LOG(WARNING) << "cannot find json item with name: "
115  << name_traits<CType>::name << ", use default empty vector.";
116  return;
117  }
118  auto ptree = pt.get_child(name_traits<CType>::name);
119  ff::util::ntobject<ARGS...> d =
120  from_ptree<ff::util::ntobject<ARGS...>>::f(ptree);
121  data.template set<CType>(std::move(d));
122  };
123 };
124 
125 template <int Index> struct to_json_helper {
126  template <typename NtObjTy>
127  static auto write(boost::property_tree::ptree &pt, const NtObjTy &data) ->
128  typename std::enable_if<(NtObjTy::type_list::len > Index), void>::type {
129  using ctype = typename ff::util::get_type_at_index_in_typelist<
130  typename NtObjTy::type_list, Index>::type;
133  }
134  template <typename NtObjTy>
135  static auto write(boost::property_tree::ptree &pt, const NtObjTy &data) ->
136  typename std::enable_if<(NtObjTy::type_list::len <= Index), void>::type {}
137 };
138 
139 template <typename... ARGS> struct to_ptree<ff::util::ntobject<ARGS...>> {
140  static boost::property_tree::ptree
141  f(const ff::util::ntobject<ARGS...> &value) {
142  boost::property_tree::ptree child;
143  to_json_helper<0>::write(child, value);
144  return child;
145  }
146 };
147 
148 template <int Index> struct from_json_helper {
149  template <typename NtObjTy>
150  static auto read(const boost::property_tree::ptree &pt, NtObjTy &data) ->
151  typename std::enable_if<(NtObjTy::type_list::len > Index), void>::type {
152  using ctype = typename ff::util::get_type_at_index_in_typelist<
153  typename NtObjTy::type_list, Index>::type;
154  using vtype = typename ff::util::internal::nt_traits<ctype>::type;
157  }
158  template <typename NtObjTy>
159  static auto read(const boost::property_tree::ptree &pt, NtObjTy &data) ->
160  typename std::enable_if<(NtObjTy::type_list::len <= Index), void>::type {}
161 };
162 
163 template <typename... ARGS> struct from_ptree<ff::util::ntobject<ARGS...>> {
164  static ff::util::ntobject<ARGS...>
165  f(const boost::property_tree::ptree &ptree) {
166  ff::util::ntobject<ARGS...> ret;
167  from_json_helper<0>::read(ptree, ret);
168  return ret;
169  }
170 };
171 
172 } // namespace internal
173 
174 class ntjson {
175 public:
176  template <typename NtObjTy> static std::string to_json(const NtObjTy &data) {
177  boost::property_tree::ptree pt;
179  std::stringstream ss;
180  boost::property_tree::write_json(ss, pt);
181  return ss.str();
182  }
183  template <typename NtObjTy>
184  static void to_json_file(const NtObjTy &data, const std::string &path) {
185  boost::property_tree::ptree pt;
187  boost::property_tree::json_parser::write_json(path, pt);
188  }
189 
190  template <typename NtObjTy>
191  static NtObjTy from_json(const std::string &json_string) {
192  std::stringstream ss;
193  ss << json_string;
194  boost::property_tree::ptree pt;
195  boost::property_tree::read_json(ss, pt);
196  NtObjTy data;
198  return data;
199  }
200 
201  template <typename NtObjTy>
202  static NtObjTy from_json_file(const std::string &path) {
203  boost::property_tree::ptree pt;
204  boost::property_tree::json_parser::read_json(path, pt);
205  NtObjTy data;
207  return data;
208  }
209 };
210 } // namespace ypc
211 
ypc::internal::ptree_get_helper
Definition: ntjson.h:37
ypc::internal::to_ptree
Definition: ntjson.h:50
ypc::user_def_name
Definition: ntjson.h:8
ypc::internal::name_traits
Definition: ntjson.h:18
ypc::ntjson
Definition: ntjson.h:174
ypc::internal::from_json_helper
Definition: ntjson.h:148
ypc::internal::ptree_put_helper
Definition: ntjson.h:28
ypc::internal::from_ptree
Definition: ntjson.h:57
ypc::internal::has_name
Definition: ntjson.h:12
ypc::internal::to_json_helper
Definition: ntjson.h:125