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 
11 namespace nddem {
12 
13 // Some previews
14 struct JsonValue;
15 using json = struct JsonValue ;
16 class JsonObject ;
17 using JsonArray = std::vector<JsonValue>;
18 
19 // =============================================================================
20 class JsonObject {
21 public:
22  JsonValue & operator[] (std::string &s) ;
23  JsonValue & at(std::string &s) ;
24 
25  // subclasses of iterators and data
26  struct dat ;
27  struct iterator;
28 
31  bool exist (std::string key) ;
32 
33 
34  std::map<std::string, JsonValue> data;
35 } ;
36 
37 // =============================================================================
38 struct JsonValue
39 {
40  enum class Type { Null, Bool, Number, String, Array, Object } type;
41 
42  double number_value = 0.0;
43  bool bool_value = false;
44  std::string string_value;
47 
48  JsonValue() : type(Type::Null) {}
49  JsonValue(double n) : type(Type::Number), number_value(n) {}
50  JsonValue(bool b) : type(Type::Bool), bool_value(b) {}
51  JsonValue(std::string s) : type(Type::String), string_value(std::move(s)) {}
52  JsonValue(JsonArray a) : type(Type::Array), array_value(std::move(a)) {}
53  JsonValue(JsonObject o) : type(Type::Object), object_value(std::move(o)) {}
54  bool is_number () { return type==Type::Number ; }
55  bool is_string () { return type==Type::String ; }
56  bool is_array () { return type==Type::Array ; }
57  bool is_object () { return type==Type::Object ;}
58 
59  JsonValue & operator[] (std::string key) ;
60  template <typename T> T get() {return ;}
61 
62  auto begin()
63  {
64  if (type!=Type::Array)
65  throw std::runtime_error(std::string("Cannot iterate a non array"));
66  return array_value.begin() ;
67  }
68  auto end()
69  {
70  if (type!=Type::Array)
71  throw std::runtime_error(std::string("Cannot iterate a non array"));
72  return array_value.end() ;
73  }
74  size_t size()
75  {
76  if (type!=Type::Array)
77  throw std::runtime_error(std::string("Cannot size a non array"));
78  return array_value.size() ;
79  }
80  JsonValue & operator[] (size_t id)
81  {
82  if (type!=Type::Array)
83  throw std::runtime_error(std::string("Cannot slice a non array"));
84  return array_value[id] ;
85  }
86  //JsonObject::iterator find(std::string key) ;
87  bool exist (std::string key) ;
88 
90  {
91  if (type!=Type::Object)
92  throw std::runtime_error(std::string("Cannot get map from a non object"));
93  return object_value ;
94  }
95 
96  // Subclass JsonParser
97  class JsonParser
98  {
99  std::string text;
100  size_t pos = 0;
101 
102  public:
103  JsonValue parse(std::string txt) {text = txt ; return parse() ; }
105 
106  private:
107  void skip_whitespace() { while (pos < text.size() && std::isspace(text[pos])) ++pos; }
108  char peek() const { return pos < text.size() ? text[pos] : '\0'; }
109  char get() { return pos < text.size() ? text[pos++] : '\0'; }
110  void expect(char expected) { if (get() != expected) throw std::runtime_error(std::string("Expected '") + expected + "'");}
119  };
120 
121  static JsonValue parse(std::string &val) {JsonValue res ; JsonParser parser ; res = parser.parse(val) ; return res ; }
122 };
123 // end JsonValue
124 
125 // =============================================================================
126 //----------------------- JsonObject impl ---------------------------------------
127 struct JsonObject::dat
128 {
129 public:
130  dat(std::pair<std::string, JsonValue> p) {k = p.first ; v = p.second ; }
131  std::string key() {return k; }
132  JsonValue & value() {return v ; }
133 private:
134  std::string k ;
135  JsonValue v ;
136 } ;
137 
139 {
140  iterator(std::map<std::string,JsonValue>::iterator a) {it = a ; }
141  bool operator!=(iterator & o) {return it !=o.it; }
142  iterator & operator++() {it ++ ; return *this ;}
143  dat operator* () { return JsonObject::dat({it->first , it->second }) ; }
144 
145  private:
146  std::map<std::string,JsonValue>::iterator it ;
147 } ;
148 
149 JsonValue & JsonObject::operator[] (std::string &s) {return data[s] ; }
150 JsonValue & JsonObject::at(std::string &s) {return data.at(s) ; }
151 JsonObject::iterator JsonObject::begin() {return JsonObject::iterator({data.begin()}) ; }
152 JsonObject::iterator JsonObject::end() {return JsonObject::iterator({data.end()}) ; }
153 //JsonObject::iterator JsonObject::find(std::string key) { return JsonObject::iterator({data.find(key)}) ; }
154 bool JsonObject::exist(std::string key) {auto res = data.find(key) ; if (res==data.end()) return false ; else return true ; }
155 
156 //------------------------- JsonValue impl -------------------------------------
157 JsonValue & JsonValue::operator[] (std::string key)
158 {
159 if (type != Type::Object) throw std::runtime_error(std::string("Trying to access key in a non object"));
160  return object_value.at(key) ;
161 }
162 
163 template<> JsonValue JsonValue::get<JsonValue>() {if (type!=Type::Object) std::runtime_error(std::string("Incorrect type number")); return object_value ; }
164 template<> bool JsonValue::get<bool>() {if (type!=Type::Bool) std::runtime_error(std::string("Incorrect type number")); return bool_value ; }
165 template<> int JsonValue::get<int>() {if (type!=Type::Number) std::runtime_error(std::string("Incorrect type number")); return number_value ; }
166 template<> double JsonValue::get<double>() {if (type!=Type::Number) std::runtime_error(std::string("Incorrect type number")); return number_value ; }
167 template<> std::string JsonValue::get<std::string>() {if (type!=Type::String) std::runtime_error(std::string("Incorrect type string")); return string_value ;}
168 template<> std::vector<double> JsonValue::get<std::vector<double>>()
169 {
170  if (type!=Type::Array) std::runtime_error(std::string("Incorrect type array"));
171  std::vector<double> res ;
172  res.resize(array_value.size()) ;
173  for (size_t i = 0 ; i<array_value.size() ; i++)
174  {
175  res[i] = array_value[i].get<double>() ;
176  }
177  return res ;
178 }
179 template<> std::vector<int> JsonValue::get<std::vector<int>>()
180 {
181  if (type!=Type::Array) std::runtime_error(std::string("Incorrect type array"));
182  std::vector<int> res ;
183  res.resize(array_value.size()) ;
184  for (size_t i = 0 ; i<array_value.size() ; i++)
185  {
186  res[i] = array_value[i].get<int>() ;
187  }
188  return res ;
189 }
190 template<> std::vector<bool> JsonValue::get<std::vector<bool>>()
191 {
192  if (type!=Type::Array) std::runtime_error(std::string("Incorrect type array"));
193  std::vector<bool> 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<bool>() ;
198  }
199  return res ;
200 }
201 template<> std::vector<std::string> JsonValue::get<std::vector<std::string>>()
202 {
203  if (type!=Type::Array) std::runtime_error(std::string("Incorrect type array"));
204  std::vector<std::string> 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<std::string>() ;
209  }
210  return res ;
211 }
212 template<> std::vector<std::vector<double>> JsonValue::get<std::vector<std::vector<double>>>()
213 {
214  if (type!=Type::Array) std::runtime_error(std::string("Incorrect type array"));
215  std::vector<std::vector<double>> 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<std::vector<double>>() ;
220  }
221  return res ;
222 }
223 template<> std::map<std::string,std::string> JsonValue::get<std::map<std::string,std::string>>()
224 {
225  if (type!=Type::Object) std::runtime_error(std::string("Incorrect type object for mapping"));
226  std::map<std::string,std::string> res ;
227  for (auto [key, value] : object_value.data)
228  res[key] = value.get<std::string>() ;
229 
230  return res ;
231 }
232 
233 /*JsonObject::iterator JsonValue::find(std::string key)
234 {
235  if (type != Type::Object)
236  throw std::runtime_error(std::string("Cannot find in a non object"));
237  return object_value.find(key) ;
238 }*/
239 bool JsonValue::exist (std::string key)
240 {
241  if (type != Type::Object)
242  throw std::runtime_error(std::string("Cannot check existence in a non object"));
243  return object_value.exist(key) ;
244 }
245 
246 std::istream& operator>>(std::istream& in, JsonValue& value) {
247  std::string content((std::istreambuf_iterator<char>(in)),
248  std::istreambuf_iterator<char>());
249  value.parse(content);
250  return in ;
251 }
252 
253 std::ostream& operator<< (std::ostream& out, const JsonValue &j)
254 {
255  switch(j.type)
256  {
257  case JsonValue::Type::Null: out << "Null" ; break ;
258  case JsonValue::Type::Bool: out << (j.bool_value?"True":"False") ; break ;
259  case JsonValue::Type::Number: out << j.number_value ; break ;
260  case JsonValue::Type::String: out << j.string_value ; break ;
262  out << "[" ;
263  for (auto & v: j.array_value)
264  out << v << "," ;
265  out << "]" ;
266  break ;
268  out << "{ " ;
269  for (auto& [key, value] : j.object_value.data)
270  out << "\"" << key << "\": " << value << ", \n" ;
271  out << "}" ;
272  break ;
273  }
274  return out ;
275 }
276 
277 //====================JsonParser impl ==========================================
278 JsonValue JsonValue::JsonParser::parse()
279 {
280  skip_whitespace();
281  JsonValue result = parse_value();
282  skip_whitespace();
283  if (pos != text.size())
284  throw std::runtime_error("Unexpected trailing characters");
285  return result;
286 }
287 //---------------------------------------------
289  skip_whitespace();
290  char c = peek();
291  if (c == '"') return parse_string();
292  if (c == '-' || std::isdigit(c)) return parse_number();
293  if (c == 't') return parse_true();
294  if (c == 'f') return parse_false();
295  if (c == 'n') return parse_null();
296  if (c == '[') return parse_array();
297  if (c == '{') return parse_object();
298  throw std::runtime_error("Unexpected character in JSON input");
299 }
300 //---------------------------------------------
302  expect('n');
303  expect('u'); expect('l'); expect('l');
304  return JsonValue();
305 }
306 //---------------------------------------------
308  expect('t');
309  expect('r'); expect('u'); expect('e');
310  return JsonValue(true);
311 }
312 //---------------------------------------------
314  expect('f');
315  expect('a'); expect('l'); expect('s'); expect('e');
316  return JsonValue(false);
317 }
318 //---------------------------------------------
320  size_t start = pos;
321  if (peek() == '-') ++pos;
322  while (std::isdigit(peek())) ++pos;
323  if (peek() == '.') {
324  ++pos;
325  while (std::isdigit(peek())) ++pos;
326  }
327  if (peek() == 'e' || peek() == 'E') {
328  ++pos;
329  if (peek() == '+' || peek() == '-') ++pos;
330  while (std::isdigit(peek())) ++pos;
331  }
332  double value = std::stod(text.substr(start, pos - start));
333  return JsonValue(value);
334 }
335 //---------------------------------------------
337  expect('"');
338  std::string result;
339  while (peek() != '"') {
340  char c = get();
341  if (c == '\0') throw std::runtime_error("Unterminated string");
342  result += c;
343  }
344  expect('"');
345  return JsonValue(result);
346 }
347 //---------------------------------------------
349  expect('[');
350  skip_whitespace();
351  JsonArray arr;
352  if (peek() == ']') {
353  get();
354  return JsonValue(arr);
355  }
356 
357  while (true) {
358  skip_whitespace();
359  arr.push_back(parse_value());
360  skip_whitespace();
361  if (peek() == ',') {
362  get();
363  } else if (peek() == ']') {
364  get();
365  break;
366  } else {
367  throw std::runtime_error("Expected ',' or ']'");
368  }
369  }
370 
371  return JsonValue(arr);
372 }
373 //---------------------------------------------
375  expect('{');
376  skip_whitespace();
377  JsonObject obj;
378  if (peek() == '}') {
379  get();
380  return JsonValue(obj);
381  }
382 
383  while (true) {
384  skip_whitespace();
385  if (peek() != '"') throw std::runtime_error("Expected object key string");
386  std::string key = parse_string().string_value;
387  skip_whitespace();
388  expect(':');
389  skip_whitespace();
390  obj[key] = parse_value();
391  skip_whitespace();
392  if (peek() == ',') {
393  get();
394  } else if (peek() == '}') {
395  get();
396  break;
397  } else {
398  throw std::runtime_error("Expected ',' or '}'");
399  }
400  }
401 
402  return JsonValue(obj);
403 }
404 
405 //--------------------------------------------------
406 } // END namespace
407 #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:108
JsonValue parse(std::string txt)
Definition: json_parser.h:103
size_t pos
Definition: json_parser.h:100
void expect(char expected)
Definition: json_parser.h:110
void skip_whitespace()
Definition: json_parser.h:107
char get()
Definition: json_parser.h:109
@ 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:131
JsonValue & value()
Definition: json_parser.h:132
dat(std::pair< std::string, JsonValue > p)
Definition: json_parser.h:130
Definition: json_parser.h:139
iterator(std::map< std::string, JsonValue >::iterator a)
Definition: json_parser.h:140
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:141
iterator & operator++()
Definition: json_parser.h:142
Definition: json_parser.h:39
size_t size()
Definition: json_parser.h:74
enum nddem::JsonValue::Type type
bool is_array()
Definition: json_parser.h:56
JsonObject object_value
Definition: json_parser.h:46
bool is_object()
Definition: json_parser.h:57
JsonValue(double n)
Definition: json_parser.h:49
JsonValue(bool b)
Definition: json_parser.h:50
Type
Definition: json_parser.h:40
JsonValue()
Definition: json_parser.h:48
bool exist(std::string key)
bool is_number()
Definition: json_parser.h:54
static JsonValue parse(std::string &val)
Definition: json_parser.h:121
bool bool_value
Definition: json_parser.h:43
std::string string_value
Definition: json_parser.h:44
auto begin()
Definition: json_parser.h:62
bool is_string()
Definition: json_parser.h:55
T get()
Definition: json_parser.h:60
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:53
JsonValue(std::string s)
Definition: json_parser.h:51
JsonObject & items()
Definition: json_parser.h:89
JsonValue(JsonArray a)
Definition: json_parser.h:52
auto end()
Definition: json_parser.h:68