brace
Incredibly simple JSON parser in C++
Loading...
Searching...
No Matches
brace.h
1#ifndef __BRACE_JSON_H__
2#define __BRACE_JSON_H__
3
4#include <cassert>
5#include <sstream>
6#include <string>
7#include <unordered_map>
8#include <variant>
9#include <vector>
10
11#include "../priv/brace/tokenizer.h"
12#include "result.h"
13
14namespace brace {
15
16class JsonValue;
17
18struct JsonNullValue {};
19
20using JsonObject = std::unordered_map<std::string, JsonValue>;
21using JsonArray = std::vector<JsonValue>;
22
34class JsonValue {
35 public:
39 using Value = std::variant<
40 bool,
41 double,
42 std::string,
43 JsonObject,
44 JsonArray,
46
50 JsonValue() : m_value(JsonNullValue {}) {}
51
57 JsonValue(bool b) : m_value(b) {}
58
64 JsonValue(double d) : m_value(d) {}
65
71 JsonValue(const std::string& s) : m_value(s) {}
72
78 JsonValue(const JsonObject& obj) : m_value(obj) {}
79
85 JsonValue(const JsonArray& arr) : m_value(arr) {}
86
92 inline bool is_null() const {
93 return std::holds_alternative<JsonNullValue>(m_value);
94 }
95
101 inline bool is_bool() const {
102 return std::holds_alternative<bool>(m_value);
103 }
104
110 inline bool is_number() const {
111 return std::holds_alternative<double>(m_value);
112 }
113
119 inline bool is_string() const {
120 return std::holds_alternative<std::string>(m_value);
121 }
122
128 inline bool is_object() const {
129 return std::holds_alternative<JsonObject>(m_value);
130 }
131
137 inline bool is_array() const {
138 return std::holds_alternative<JsonArray>(m_value);
139 }
140
146 inline const Value& value() const {
147 return m_value;
148 }
149
157 inline operator std::string() const {
158 assert(is_string() && "JsonValue is not a string");
159 return std::get<std::string>(m_value);
160 }
161
169 inline operator int() const {
170 assert(is_number() && "JsonValue is not a number");
171 return static_cast<int>(std::get<double>(m_value));
172 }
173
181 inline operator double() const {
182 assert(is_number() && "JsonValue is not a number");
183 return std::get<double>(m_value);
184 }
185
193 inline operator float() const {
194 assert(is_number() && "JsonValue is not a number");
195 return static_cast<float>(std::get<double>(m_value));
196 }
197
205 inline operator size_t() const {
206 assert(is_number() && "JsonValue is not a number");
207 return static_cast<size_t>(std::get<double>(m_value));
208 }
209
217 inline operator bool() const {
218 assert(is_bool() && "JsonValue is not a bool");
219 return std::get<bool>(m_value);
220 }
221
229 inline const JsonArray& to_array() const {
230 assert(is_array() && "JsonValue is not an array");
231 return std::get<JsonArray>(m_value);
232 }
233
240 inline bool operator==(const std::string& other) const {
241 if (std::holds_alternative<std::string>(m_value)) {
242 return std::get<std::string>(m_value) == other;
243 }
244 return false;
245 }
246
253 inline bool operator==(const char* other) const {
254 return *this == std::string(other);
255 }
256
263 inline bool operator==(double other) const {
264 if (std::holds_alternative<double>(m_value)) {
265 return std::get<double>(m_value) == other;
266 }
267 return false;
268 }
269
276 inline bool operator==(int other) const {
277 if (std::holds_alternative<double>(m_value)) {
278 return std::get<double>(m_value) == other;
279 }
280 return false;
281 }
282
291 inline const JsonValue& operator[](const std::string& key) const {
292 return operator[](key.c_str());
293 }
294
303 inline const JsonValue& operator[](const char* key) const {
304 assert(is_object() && "JsonValue is not an object");
305 return std::get<JsonObject>(m_value).at(key);
306 }
307
316 inline const JsonValue& operator[](size_t index) const {
317 assert(is_array() && "JsonValue is not an array");
318 return std::get<JsonArray>(m_value).at(index);
319 }
320
321 private:
322 Value m_value;
323};
324
326 public:
327 template<typename... Args>
328 ParseError(size_t line, size_t column, Args&&... args) :
329 m_line(line),
330 m_column(column) {
331 std::ostringstream oss;
332 (oss << ... << args);
333 m_message = oss.str();
334 }
335
336 std::string_view message() const {
337 return m_message;
338 }
339
340 operator std::string() const {
341 return m_message;
342 }
343
344 private:
345 std::string m_message;
346 size_t m_line;
347 size_t m_column;
348};
349
363class Parser {
364 public:
378 Result<JsonValue, ParseError> parse(const std::string& json);
379
380 private:
381 std::vector<::priv::brace::Token> m_tokens;
382 size_t m_current;
383
384 const ::priv::brace::Token& peek() const {
385 return m_tokens[m_current];
386 }
387
388 const ::priv::brace::Token& advance() {
389 return m_tokens[m_current++];
390 }
391
392 bool is_at_end() const {
393 return m_current >= m_tokens.size();
394 }
395
396 Result<JsonValue, ParseError> parse_value();
397 Result<JsonObject, ParseError> parse_object();
398 Result<JsonArray, ParseError> parse_array();
399};
400
401} // namespace brace
402
403#endif
Represents a flexible JSON value that can hold different types of data.
Definition brace.h:34
const JsonValue & operator[](size_t index) const
Accesses an array's value by index.
Definition brace.h:316
bool is_string() const
Checks if the current value is a string.
Definition brace.h:119
bool operator==(const std::string &other) const
Compares the JsonValue with a string.
Definition brace.h:240
JsonValue(bool b)
Constructs a JSON value from a boolean.
Definition brace.h:57
JsonValue(const JsonObject &obj)
Constructs a JSON value from an object (map of key-value pairs).
Definition brace.h:78
std::variant< bool, double, std::string, JsonObject, JsonArray, JsonNullValue > Value
Internal type definition for storing different JSON value types.
Definition brace.h:39
const JsonValue & operator[](const char *key) const
Accesses an object's value by C-style string key.
Definition brace.h:303
JsonValue(const std::string &s)
Constructs a JSON value from a string.
Definition brace.h:71
bool is_number() const
Checks if the current value is a number.
Definition brace.h:110
bool is_bool() const
Checks if the current value is a boolean.
Definition brace.h:101
bool operator==(int other) const
Compares the JsonValue with an integer.
Definition brace.h:276
const JsonArray & to_array() const
Retrieves the array value of the JsonValue.
Definition brace.h:229
bool is_object() const
Checks if the current value is an object.
Definition brace.h:128
bool is_array() const
Checks if the current value is an array.
Definition brace.h:137
JsonValue(const JsonArray &arr)
Constructs a JSON value from an array.
Definition brace.h:85
bool operator==(const char *other) const
Compares the JsonValue with a C-style string.
Definition brace.h:253
JsonValue()
Default constructor. Creates a null JSON value.
Definition brace.h:50
JsonValue(double d)
Constructs a JSON value from a numeric value.
Definition brace.h:64
const JsonValue & operator[](const std::string &key) const
Accesses an object's value by string key.
Definition brace.h:291
bool is_null() const
Checks if the current value is null.
Definition brace.h:92
const Value & value() const
Retrieves the internal variant value.
Definition brace.h:146
bool operator==(double other) const
Compares the JsonValue with a double.
Definition brace.h:263
Definition brace.h:325
A JSON parsing class for converting JSON strings to JsonValue objects.
Definition brace.h:363
Result< JsonValue, ParseError > parse(const std::string &json)
Parses a JSON-formatted string into a JsonValue.
Definition result.h:16
Definition brace.h:18