json_value.h
1 /*
2 ** ClanLib SDK
3 ** Copyright (c) 1997-2015 The ClanLib Team
4 **
5 ** This software is provided 'as-is', without any express or implied
6 ** warranty. In no event will the authors be held liable for any damages
7 ** arising from the use of this software.
8 **
9 ** Permission is granted to anyone to use this software for any purpose,
10 ** including commercial applications, and to alter it and redistribute it
11 ** freely, subject to the following restrictions:
12 **
13 ** 1. The origin of this software must not be misrepresented; you must not
14 ** claim that you wrote the original software. If you use this software
15 ** in a product, an acknowledgment in the product documentation would be
16 ** appreciated but is not required.
17 ** 2. Altered source versions must be plainly marked as such, and must not be
18 ** misrepresented as being the original software.
19 ** 3. This notice may not be removed or altered from any source distribution.
20 **
21 ** Note: Some of the libraries ClanLib may link to may have additional
22 ** requirements or restrictions.
23 **
24 ** File Author(s):
25 **
26 ** Magnus Norddahl
27 */
28 
29 #pragma once
30 
31 #include <map>
32 #include <vector>
33 
34 namespace clan
35 {
38 
40 class JsonException : public Exception
41 {
42 public:
43  JsonException(const std::string &message) : Exception(message) { }
44 };
45 
47 class JsonValue
48 {
49 public:
51  enum class Type
52  {
53  undefined,
54  null,
55  object,
56  array,
57  string,
58  number,
59  boolean
60  };
61 
64 public:
66  static JsonValue object() { return JsonValue(Type::object); }
67 
69  static JsonValue array() { return JsonValue(Type::array); }
70 
72  static JsonValue null() { return JsonValue(Type::null); }
73 
75  static JsonValue string(const std::string &value) { return JsonValue(value); }
76 
78  static JsonValue boolean(bool value) { return JsonValue(value); }
79 
81  static JsonValue number(int value) { return JsonValue(value); }
82  static JsonValue number(double value) { return JsonValue(value); }
83 
85  static JsonValue from_json(const std::string &json);
86 
88  JsonValue() : type(Type::undefined), value_number(), value_boolean() { }
89  JsonValue(Type type) : type(type), value_number(), value_boolean() { }
90  JsonValue(bool value) : type(Type::boolean), value_number(), value_boolean(value) { }
91  JsonValue(int value) : type(Type::number), value_number((double)value), value_boolean() { }
92  JsonValue(double value) : type(Type::number), value_number(value), value_boolean() { }
93  JsonValue(const char *value) : type(Type::string), value_string(value), value_number(), value_boolean() { }
94  JsonValue(const std::string &value) : type(Type::string), value_string(value), value_number(), value_boolean() { }
96 
99 public:
101  explicit operator bool() const { return to_boolean(); }
102  operator std::string() const { return to_string(); }
103  operator float() const { return to_float(); }
104  operator double() const { return to_double(); }
105  operator int() const { return to_int(); }
106 
108  JsonValue &operator[](const char *key) { return members[key]; }
109  JsonValue &operator[](const std::string &key) { return members[key]; }
110  const JsonValue &operator[](const char *key) const
111  {
112  static JsonValue undefined;
113  auto it = members.find(key);
114  if (it == members.end()) return undefined;
115  else return it->second;
116  }
117  const JsonValue &operator[](const std::string &key) const
118  {
119  static JsonValue undefined;
120  auto it = members.find(key);
121  if (it == members.end()) return undefined;
122  else return it->second;
123  }
124 
125  const JsonValue &operator[](int index) const { return items[index]; }
126  JsonValue &operator[](int index) { return items[index]; }
127 
129  Type get_type() const { return type; }
130 
132  size_t get_size() const
133  {
134  switch (type)
135  {
136  case Type::object: return members.size();
137  case Type::array: return items.size();
138  case Type::string: return value_string.size();
139  default: return 0;
140  }
141  }
142 
144  std::map<std::string, JsonValue> &get_members() { return members; }
145  const std::map<std::string, JsonValue> &get_members() const { return members; }
146 
148  std::vector<JsonValue> &get_items() { return items; }
149  const std::vector<JsonValue> &get_items() const { return items; }
150 
152  bool is_undefined() const { return type == Type::undefined; }
153 
155  bool is_null() const { return type == Type::null; }
156 
158  bool is_object() const { return type == Type::object; }
159 
161  bool is_array() const { return type == Type::array; }
162 
164  bool is_string() const { return type == Type::string; }
165 
167  bool is_number() const { return type == Type::number; }
168 
170  bool is_boolean() const { return type == Type::boolean; }
171 
173  std::string to_string() const { if (type != Type::string) throw JsonException("JSON Value is not a string"); return value_string; }
174 
176  int to_int() const { if (type != Type::number) throw JsonException("JSON Value is not a number"); return (int)value_number; }
177 
179  float to_float() const { if (type != Type::number) throw JsonException("JSON Value is not a number"); return (float)value_number; }
180 
182  double to_double() const { if (type != Type::number) throw JsonException("JSON Value is not a number"); return value_number; }
183 
185  bool to_boolean() const { if (type != Type::boolean) throw JsonException("JSON Value is not a boolean"); return value_boolean; }
187 
190 public:
192  template<typename T>
193  JsonValue &operator =(const T &value) { *this = JsonValue(value); return *this; }
194 
196  {
197  type = value.type;
198  members = value.members;
199  items = value.items;
200  value_string = value.value_string;
201  value_number = value.value_number;
202  value_boolean = value.value_boolean;
203  return *this;
204  }
205 
207  template<typename Type>
208  std::map<std::string, Type> to_map() const
209  {
210  if (type != Type::object)
211  throw JsonException("JSON Value is not an object");
212 
213  std::map<std::string, Type> object;
214  std::map<std::string, JsonValue>::const_iterator it;
215  for (it = members.begin(); it != members.end(); ++it)
216  object[it->first] = it->second;
217  return object;
218  }
219 
221  template<typename Type>
222  std::vector<Type> to_vector() const
223  {
224  if (type != Type::array)
225  throw JsonException("JSON Value is not an array");
226 
227  std::vector<Type> list;
228  list.reserve(items.size());
229  for (auto & elem : items)
230  list.push_back(elem);
231  return list;
232  }
233 
235  std::string to_json() const;
236  void to_json(std::string &result) const;
238 
241 private:
242  void write(std::string &json) const;
243  void write_array(std::string &json) const;
244  void write_object(std::string &json) const;
245  static void write_string(const std::string &str, std::string &json);
246  void write_number(std::string &json) const;
247 
248  static JsonValue read(const std::string &json, size_t &pos);
249  static JsonValue read_object(const std::string &json, size_t &pos);
250  static JsonValue read_array(const std::string &json, size_t &pos);
251  static std::string read_string(const std::string &json, size_t &pos);
252  static JsonValue read_number(const std::string &json, size_t &pos);
253  static JsonValue read_boolean(const std::string &json, size_t &pos);
254  static void read_whitespace(const std::string &json, size_t &pos);
255 
256  Type type;
257  std::map<std::string, JsonValue> members;
258  std::vector<JsonValue> items;
259  std::string value_string;
260  double value_number;
261  bool value_boolean;
263 };
264 
266 }
std::map< std::string, JsonValue > & get_members()
Get object members.
Definition: json_value.h:144
JsonValue & operator[](const std::string &key)
Definition: json_value.h:109
int to_int() const
Convert value object to an int.
Definition: json_value.h:176
bool is_number() const
Return true if value is a number.
Definition: json_value.h:167
const std::vector< JsonValue > & get_items() const
Definition: json_value.h:149
bool is_array() const
Return true if value is an array.
Definition: json_value.h:161
JsonValue(int value)
Definition: json_value.h:91
bool is_object() const
Return true if value is an object.
Definition: json_value.h:158
std::string message
Description of exception.
Definition: exception.h:58
bool is_undefined() const
Return true if value is undefined.
Definition: json_value.h:152
static JsonValue string(const std::string &value)
Create a string value.
Definition: json_value.h:75
static JsonValue number(double value)
Definition: json_value.h:82
JsonValue(Type type)
Definition: json_value.h:89
std::string to_json() const
Create an UTF-8 JSON string for the value.
Exception class thrown for JSON exceptions.
Definition: json_value.h:41
JsonValue()
Constructs a value.
Definition: json_value.h:88
JsonValue & operator=(const T &value)
Assign a new value.
Definition: json_value.h:193
JsonValue(double value)
Definition: json_value.h:92
bool is_null() const
Return true if value is null.
Definition: json_value.h:155
const std::map< std::string, JsonValue > & get_members() const
Definition: json_value.h:145
static JsonValue boolean(bool value)
Create a boolean value.
Definition: json_value.h:78
Class representing a JSON value.
Definition: json_value.h:48
float to_float() const
Convert value object to a float.
Definition: json_value.h:179
size_t get_size() const
Get size of value.
Definition: json_value.h:132
std::string to_string() const
Convert value object to a string.
Definition: json_value.h:173
void to_json(std::string &result) const
bool to_boolean() const
Convert value object to a boolean.
Definition: json_value.h:185
static JsonValue object()
Create a object value.
Definition: json_value.h:66
JsonException(const std::string &message)
Definition: json_value.h:43
const JsonValue & operator[](int index) const
Definition: json_value.h:125
const JsonValue & operator[](const std::string &key) const
Definition: json_value.h:117
Definition: clanapp.h:36
JsonValue & operator[](const char *key)
Indexers for object members or array items.
Definition: json_value.h:108
double to_double() const
Convert value object to a double.
Definition: json_value.h:182
Type get_type() const
Get value type.
Definition: json_value.h:129
Top-level exception class.
Definition: exception.h:43
const JsonValue & operator[](const char *key) const
Definition: json_value.h:110
bool is_string() const
Return true if value is a string.
Definition: json_value.h:164
bool is_boolean() const
Return true if value is a boolean.
Definition: json_value.h:170
JsonValue & operator[](int index)
Definition: json_value.h:126
JsonValue(bool value)
Definition: json_value.h:90
Type
value type
Definition: json_value.h:52
std::vector< JsonValue > & get_items()
Get array items.
Definition: json_value.h:148
static JsonValue array()
Create a array value.
Definition: json_value.h:69
std::vector< Type > to_vector() const
Convert value array to a std::vector with the template specified value type.
Definition: json_value.h:222
JsonValue(const char *value)
Definition: json_value.h:93
JsonValue(const std::string &value)
Definition: json_value.h:94
static JsonValue from_json(const std::string &json)
Create a value from UTF-8 JSON string.
std::map< std::string, Type > to_map() const
Convert value object to a std::map with the template specified value type.
Definition: json_value.h:208
static JsonValue number(int value)
Create a number value.
Definition: json_value.h:81