NDDEM
json_parser.h
Go to the documentation of this file.
1 #ifndef NDDEMJSON
2 #define NDDEMJSON
3 #include <string>
4 #include <map>
5 #include <vector>
6 #include <stdexcept>
7 #include <fstream>
8 #include <cctype>
9 #include <cstdlib>
10 #include <regex>
11 
12 namespace nddem {
13 
14 // Some previews
15 struct JsonValue;
16 using json = struct JsonValue ;
17 class JsonObject ;
18 using JsonArray = std::vector<JsonValue>;
19 
20 // =============================================================================
21 class JsonObject {
22 public:
23  JsonValue & operator[] (std::string &s) ;
24  JsonValue & at(std::string &s) ;
25 
26  // subclasses of iterators and data
27  struct dat ;
28  struct iterator;
29 
32  bool exist (std::string key) ;
33 
34 
35  std::map<std::string, JsonValue> data;
36 } ;
37 
38 // =============================================================================
39 struct JsonValue
40 {
41  enum class Type { Null, Bool, Number, String, Array, Object } type;
42 
43  double number_value = 0.0;
44  bool bool_value = false;
45  std::string string_value;
48 
49  JsonValue() : type(Type::Null) {}
50  JsonValue(double n) : type(Type::Number), number_value(n) {}
51  JsonValue(bool b) : type(Type::Bool), bool_value(b) {}
52  JsonValue(std::string s) : type(Type::String), string_value(std::move(s)) {}
53  JsonValue(JsonArray a) : type(Type::Array), array_value(std::move(a)) {}
54  JsonValue(JsonObject o) : type(Type::Object), object_value(std::move(o)) {}
55  bool is_number () { return type==Type::Number ; }
56  bool is_string () { return type==Type::String ; }
57  bool is_array () { return type==Type::Array ; }
58  bool is_object () { return type==Type::Object ;}
59 
60  JsonValue & operator[] (std::string key) ;
61  template <typename T> T get() {return ;}
62 
63  auto begin()
64  {
65  if (type!=Type::Array)
66  throw std::runtime_error(std::string("Cannot iterate a non array"));
67  return array_value.begin() ;
68  }
69  auto end()
70  {
71  if (type!=Type::Array)
72  throw std::runtime_error(std::string("Cannot iterate a non array"));
73  return array_value.end() ;
74  }
75  size_t size()
76  {
77  if (type!=Type::Array)
78  throw std::runtime_error(std::string("Cannot size a non array"));
79  return array_value.size() ;
80  }
81  JsonValue & operator[] (size_t id)
82  {
83  if (type!=Type::Array)
84  throw std::runtime_error(std::string("Cannot slice a non array"));
85  return array_value[id] ;
86  }
87  //JsonObject::iterator find(std::string key) ;
88  bool exist (std::string key) ;
89 
91  {
92  if (type!=Type::Object)
93  {
94  throw std::runtime_error(std::string("Cannot get map from a non object"));
95  }
96  return object_value ;
97  }
98 
99  // Subclass JsonParser
100  class JsonParser
101  {
102  std::string text;
103  size_t pos = 0;
104 
105  public:
106  JsonValue parse(std::string txt) {text = txt ; process_env(text) ; return parse() ; }
108 
109  private:
110  void skip_whitespace() { while (pos < text.size() && std::isspace(text[pos])) ++pos; }
111  char peek() const { return pos < text.size() ? text[pos] : '\0'; }
112  char get() { return pos < text.size() ? text[pos++] : '\0'; }
113  void expect(char expected) { if (get() != expected) throw std::runtime_error(std::string("Expected '") + expected + "'");}
122 
123  int process_env(std::string &in)
124  {
125  int replacements = 0;
126  std::regex reg("[$][a-zA-Z0-9]+");
127  auto envvar = std::sregex_iterator(in.begin(), in.end(), reg);
128  auto endenvvar = std::sregex_iterator();
129  while (envvar != endenvvar)
130  {
131  std::smatch match = *(envvar) ;
132  std::string val =std::string(std::getenv(match.str().substr(1).c_str())) ;
133  in=in.replace(match.position(), match.length(), val) ;
134  envvar = std::sregex_iterator(in.begin(), in.end(), reg);
135  replacements ++ ;
136  }
137  if (replacements>0) std::cout << "====Replaced\n" << in ;
138  return 0 ;
139  }
140  };
141 
142  static JsonValue parse(std::string &val) {JsonValue res ; JsonParser parser ; res = parser.parse(val) ; return res ; }
143 
144 };
145 // end JsonValue
146 
147 // =============================================================================
148 //----------------------- JsonObject impl ---------------------------------------
149 struct JsonObject::dat
150 {
151 public:
152  dat(std::pair<std::string, JsonValue> p) {k = p.first ; v = p.second ; }
153  std::string key() {return k; }
154  JsonValue & value() {return v ; }
155 private:
156  std::string k ;
157  JsonValue v ;
158 } ;
159 
161 {
162  iterator(std::map<std::string,JsonValue>::iterator a) {it = a ; }
163  bool operator!=(iterator & o) {return it !=o.it; }
164  iterator & operator++() {it ++ ; return *this ;}
165  dat operator* () { return JsonObject::dat({it->first , it->second }) ; }
166 
167  private:
168  std::map<std::string,JsonValue>::iterator it ;
169 } ;
170 
171 JsonValue & JsonObject::operator[] (std::string &s) {return data[s] ; }
172 JsonValue & JsonObject::at(std::string &s) {return data.at(s) ; }
173 JsonObject::iterator JsonObject::begin() {return JsonObject::iterator({data.begin()}) ; }
174 JsonObject::iterator JsonObject::end() {return JsonObject::iterator({data.end()}) ; }
175 //JsonObject::iterator JsonObject::find(std::string key) { return JsonObject::iterator({data.find(key)}) ; }
176 bool JsonObject::exist(std::string key) {auto res = data.find(key) ; if (res==data.end()) return false ; else return true ; }
177 
178 //------------------------- JsonValue impl -------------------------------------
179 JsonValue & JsonValue::operator[] (std::string key)
180 {
181 if (type != Type::Object) throw std::runtime_error(std::string("Trying to access key in a non object"));
182  return object_value.at(key) ;
183 }
184 
185 template<> JsonValue JsonValue::get<JsonValue>() {if (type!=Type::Object) std::runtime_error(std::string("Incorrect type number")); return object_value ; }
186 template<> bool JsonValue::get<bool>() {if (type!=Type::Bool) std::runtime_error(std::string("Incorrect type number")); return bool_value ; }
187 template<> int JsonValue::get<int>() {if (type!=Type::Number) std::runtime_error(std::string("Incorrect type number")); return number_value ; }
188 template<> double JsonValue::get<double>() {if (type!=Type::Number) std::runtime_error(std::string("Incorrect type number")); return number_value ; }
189 template<> std::string JsonValue::get<std::string>() {if (type!=Type::String) std::runtime_error(std::string("Incorrect type string")); return string_value ;}
190 template<> std::vector<double> JsonValue::get<std::vector<double>>()
191 {
192  if (type!=Type::Array) std::runtime_error(std::string("Incorrect type array"));
193  std::vector<double> res ;
194  res.resize(array_value.size()) ;
195  for (size_t i = 0 ; i<array_value.size() ; i++)
196  {
197  res[i] = array_value[i].get<double>() ;
198  }
199  return res ;
200 }
201 template<> std::vector<int> JsonValue::get<std::vector<int>>()
202 {
203  if (type!=Type::Array) std::runtime_error(std::string("Incorrect type array"));
204  std::vector<int> res ;
205  res.resize(array_value.size()) ;
206  for (size_t i = 0 ; i<array_value.size() ; i++)
207  {
208  res[i] = array_value[i].get<int>() ;
209  }
210  return res ;
211 }
212 template<> std::vector<bool> JsonValue::get<std::vector<bool>>()
213 {
214  if (type!=Type::Array) std::runtime_error(std::string("Incorrect type array"));
215  std::vector<bool> res ;
216  res.resize(array_value.size()) ;
217  for (size_t i = 0 ; i<array_value.size() ; i++)
218  {
219  res[i] = array_value[i].get<bool>() ;
220  }
221  return res ;
222 }
223 template<> std::vector<std::string> JsonValue::get<std::vector<std::string>>()
224 {
225  if (type!=Type::Array) std::runtime_error(std::string("Incorrect type array"));
226  std::vector<std::string> res ;
227  res.resize(array_value.size()) ;
228  for (size_t i = 0 ; i<array_value.size() ; i++)
229  {
230  res[i] = array_value[i].get<std::string>() ;
231  }
232  return res ;
233 }
234 template<> std::vector<std::vector<double>> JsonValue::get<std::vector<std::vector<double>>>()
235 {
236  if (type!=Type::Array) std::runtime_error(std::string("Incorrect type array"));
237  std::vector<std::vector<double>> res ;
238  res.resize(array_value.size()) ;
239  for (size_t i = 0 ; i<array_value.size() ; i++)
240  {
241  res[i] = array_value[i].get<std::vector<double>>() ;
242  }
243  return res ;
244 }
245 template<> std::map<std::string,std::string> JsonValue::get<std::map<std::string,std::string>>()
246 {
247  if (type!=Type::Object) std::runtime_error(std::string("Incorrect type object for mapping"));
248  std::map<std::string,std::string> res ;
249  for (auto [key, value] : object_value.data)
250  res[key] = value.get<std::string>() ;
251 
252  return res ;
253 }
254 
255 /*JsonObject::iterator JsonValue::find(std::string key)
256 {
257  if (type != Type::Object)
258  throw std::runtime_error(std::string("Cannot find in a non object"));
259  return object_value.find(key) ;
260 }*/
261 bool JsonValue::exist (std::string key)
262 {
263  if (type != Type::Object)
264  throw std::runtime_error(std::string("Cannot check existence in a non object"));
265  return object_value.exist(key) ;
266 }
267 
268 std::istream& operator>>(std::istream& in, JsonValue& value) {
269  std::string content((std::istreambuf_iterator<char>(in)),
270  std::istreambuf_iterator<char>());
271  value=value.parse(content);
272  return in ;
273 }
274 
275 std::ostream& operator<< (std::ostream& out, const JsonValue &j)
276 {
277  switch(j.type)
278  {
279  case JsonValue::Type::Null: out << "Null" ; break ;
280  case JsonValue::Type::Bool: out << (j.bool_value?"True":"False") ; break ;
281  case JsonValue::Type::Number: out << j.number_value ; break ;
282  case JsonValue::Type::String: out << j.string_value ; break ;
284  out << "[" ;
285  for (auto & v: j.array_value)
286  out << v << "," ;
287  out << "]" ;
288  break ;
290  out << "{ " ;
291  for (auto& [key, value] : j.object_value.data)
292  out << "\"" << key << "\": " << value << ", \n" ;
293  out << "}" ;
294  break ;
295  }
296  return out ;
297 }
298 
299 //====================JsonParser impl ==========================================
300 JsonValue JsonValue::JsonParser::parse()
301 {
302  skip_whitespace();
303  JsonValue result = parse_value();
304  skip_whitespace();
305  if (pos != text.size())
306  throw std::runtime_error("Unexpected trailing characters");
307  return result;
308 }
309 //---------------------------------------------
311  skip_whitespace();
312  char c = peek();
313  if (c == '"') return parse_string();
314  if (c == '-' || std::isdigit(c)) return parse_number();
315  if (c == 't') return parse_true();
316  if (c == 'f') return parse_false();
317  if (c == 'n') return parse_null();
318  if (c == '[') return parse_array();
319  if (c == '{') return parse_object();
320  throw std::runtime_error("Unexpected character in JSON input");
321 }
322 //---------------------------------------------
324  expect('n');
325  expect('u'); expect('l'); expect('l');
326  return JsonValue();
327 }
328 //---------------------------------------------
330  expect('t');
331  expect('r'); expect('u'); expect('e');
332  return JsonValue(true);
333 }
334 //---------------------------------------------
336  expect('f');
337  expect('a'); expect('l'); expect('s'); expect('e');
338  return JsonValue(false);
339 }
340 //---------------------------------------------
342  size_t start = pos;
343  if (peek() == '-') ++pos;
344  while (std::isdigit(peek())) ++pos;
345  if (peek() == '.') {
346  ++pos;
347  while (std::isdigit(peek())) ++pos;
348  }
349  if (peek() == 'e' || peek() == 'E') {
350  ++pos;
351  if (peek() == '+' || peek() == '-') ++pos;
352  while (std::isdigit(peek())) ++pos;
353  }
354  double value = std::stod(text.substr(start, pos - start));
355  return JsonValue(value);
356 }
357 //---------------------------------------------
359  expect('"');
360  std::string result;
361  while (peek() != '"') {
362  char c = get();
363  if (c == '\0') throw std::runtime_error("Unterminated string");
364  result += c;
365  }
366  expect('"');
367  return JsonValue(result);
368 }
369 //---------------------------------------------
371  expect('[');
372  skip_whitespace();
373  JsonArray arr;
374  if (peek() == ']') {
375  get();
376  return JsonValue(arr);
377  }
378 
379  while (true) {
380  skip_whitespace();
381  arr.push_back(parse_value());
382  skip_whitespace();
383  if (peek() == ',') {
384  get();
385  } else if (peek() == ']') {
386  get();
387  break;
388  } else {
389  throw std::runtime_error("Expected ',' or ']'");
390  }
391  }
392 
393  return JsonValue(arr);
394 }
395 //---------------------------------------------
397  expect('{');
398  skip_whitespace();
399  JsonObject obj;
400  if (peek() == '}') {
401  get();
402  return JsonValue(obj);
403  }
404 
405  while (true) {
406  skip_whitespace();
407  if (peek() != '"') throw std::runtime_error("Expected object key string");
408  std::string key = parse_string().string_value;
409  skip_whitespace();
410  expect(':');
411  skip_whitespace();
412  obj[key] = parse_value();
413  skip_whitespace();
414  if (peek() == ',') {
415  get();
416  } else if (peek() == '}') {
417  get();
418  break;
419  } else {
420  throw std::runtime_error("Expected ',' or '}'");
421  }
422  }
423 
424  return JsonValue(obj);
425 }
426 
427 //--------------------------------------------------
428 } // END namespace
429 #endif
namespace for Niels Lohmann
Definition: json.hpp:20203
Definition: json_parser.h:20
iterator end()
Definition: json_parser.h:152
JsonValue & at(std::string &s)
Definition: json_parser.h:150
std::map< std::string, JsonValue > data
Definition: json_parser.h:34
JsonValue & operator[](std::string &s)
Definition: json_parser.h:149
JsonValue & at(std::string &s)
bool exist(std::string key)
iterator begin()
iterator begin()
Definition: json_parser.h:151
Definition: json_parser.h:98
std::string text
Definition: json_parser.h:99
char peek() const
Definition: json_parser.h:111
JsonValue parse(std::string txt)
Definition: json_parser.h:106
size_t pos
Definition: json_parser.h:100
int process_env(std::string &in)
Definition: json_parser.h:123
void expect(char expected)
Definition: json_parser.h:113
void skip_whitespace()
Definition: json_parser.h:110
char get()
Definition: json_parser.h:112
@ pos
Definition: Typedefs.h:19
type
The type the bitset is encoded with.
Definition: bitset.hpp:44
@ key
the parser read a key of a value in an object
Definition: json_parser.h:11
std::vector< JsonValue > JsonArray
Definition: json_parser.h:17
std::ostream & operator<<(std::ostream &out, const JsonValue &j)
Definition: json_parser.h:253
std::istream & operator>>(std::istream &in, JsonValue &value)
Definition: json_parser.h:246
Definition: json.hpp:5678
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1282
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition: pointer.h:1181
PUGI_IMPL_FN xpath_string string_value(const xpath_node &na, xpath_allocator *alloc)
Definition: pugixml.cpp:8147
Definition: json_parser.h:128
std::string k
Definition: json_parser.h:134
JsonValue v
Definition: json_parser.h:135
std::string key()
Definition: json_parser.h:153
JsonValue & value()
Definition: json_parser.h:154
dat(std::pair< std::string, JsonValue > p)
Definition: json_parser.h:152
Definition: json_parser.h:139
iterator(std::map< std::string, JsonValue >::iterator a)
Definition: json_parser.h:162
std::map< std::string, JsonValue >::iterator it
Definition: json_parser.h:146
dat operator*()
Definition: json_parser.h:143
bool operator!=(iterator &o)
Definition: json_parser.h:163
iterator & operator++()
Definition: json_parser.h:164
Definition: json_parser.h:39
size_t size()
Definition: json_parser.h:75
enum nddem::JsonValue::Type type
bool is_array()
Definition: json_parser.h:57
JsonObject object_value
Definition: json_parser.h:46
bool is_object()
Definition: json_parser.h:58
JsonValue(double n)
Definition: json_parser.h:50
JsonValue(bool b)
Definition: json_parser.h:51
Type
Definition: json_parser.h:40
JsonValue()
Definition: json_parser.h:49
bool exist(std::string key)
bool is_number()
Definition: json_parser.h:55
static JsonValue parse(std::string &val)
Definition: json_parser.h:142
bool bool_value
Definition: json_parser.h:43
std::string string_value
Definition: json_parser.h:44
auto begin()
Definition: json_parser.h:63
bool is_string()
Definition: json_parser.h:56
T get()
Definition: json_parser.h:61
double number_value
Definition: json_parser.h:42
JsonArray array_value
Definition: json_parser.h:45
JsonValue & operator[](std::string key)
Definition: json_parser.h:157
JsonValue(JsonObject o)
Definition: json_parser.h:54
JsonValue(std::string s)
Definition: json_parser.h:52
JsonObject & items()
Definition: json_parser.h:90
JsonValue(JsonArray a)
Definition: json_parser.h:53
auto end()
Definition: json_parser.h:69