19 class JsonElementImpl {
22 bool bBoolValue =
false;
23 double dNumValue = 0.0;
25 Collections::Generic::List<JsonElement> lstArray;
26 Collections::Generic::Dictionary<String, JsonElement> dictObject;
28 JsonElementImpl() =
default;
34 std::string sResult =
"\"";
39 case '\"': sResult +=
"\\\"";
break;
40 case '\\': sResult +=
"\\\\";
break;
41 case '\b': sResult +=
"\\b";
break;
42 case '\f': sResult +=
"\\f";
break;
43 case '\n': sResult +=
"\\n";
break;
44 case '\r': sResult +=
"\\r";
break;
45 case '\t': sResult +=
"\\t";
break;
47 if (
static_cast<unsigned char>(c) < 32) {
49 ss <<
"\\u" << std::setfill(
'0') << std::setw(4) << std::hex << static_cast<int>(c);
59 return String(sResult.c_str());
64 static JsonElement Parse(
const String& sJson) {
68 SkipWhitespace(s, index);
69 JsonElement res = ParseValue(s, index);
70 SkipWhitespace(s, index);
71 if (index < s.length()) {
78 static void SkipWhitespace(
const std::string& s,
size_t& index) {
80 while (index < s.length() && (s[index] ==
' ' || s[index] ==
'\t' || s[index] ==
'\n' || s[index] ==
'\r')) {
85 static JsonElement ParseValue(
const std::string& s,
size_t& index) {
87 SkipWhitespace(s, index);
88 if (index >= s.length()) {
93 return ParseObject(s, index);
94 }
else if (c ==
'[') {
95 return ParseArray(s, index);
96 }
else if (c ==
'\"') {
97 return ParseString(s, index);
98 }
else if (c ==
't' || c ==
'f') {
99 return ParseBool(s, index);
100 }
else if (c ==
'n') {
101 return ParseNull(s, index);
102 }
else if (c ==
'-' || std::isdigit(
static_cast<unsigned char>(c))) {
103 return ParseNumber(s, index);
105 throw JsonException((std::string(
"Unexpected character: ") + c).c_str());
109 static JsonElement ParseObject(
const std::string& s,
size_t& index) {
113 SkipWhitespace(s, index);
114 if (index < s.length() && s[index] ==
'}') {
119 SkipWhitespace(s, index);
120 if (index >= s.length() || s[index] !=
'\"') {
123 JsonElement keyEl = ParseString(s, index);
124 String key = keyEl.GetString();
125 SkipWhitespace(s, index);
126 if (index >= s.length() || s[index] !=
':') {
130 JsonElement val = ParseValue(s, index);
131 obj.SetProperty(key, val);
132 SkipWhitespace(s, index);
133 if (index < s.length() && s[index] ==
'}') {
137 if (index >= s.length() || s[index] !=
',') {
145 static JsonElement ParseArray(
const std::string& s,
size_t& index) {
149 SkipWhitespace(s, index);
150 if (index < s.length() && s[index] ==
']') {
155 JsonElement val = ParseValue(s, index);
156 arr.AddArrayElement(val);
157 SkipWhitespace(s, index);
158 if (index < s.length() && s[index] ==
']') {
162 if (index >= s.length() || s[index] !=
',') {
170 static void ParseUnicodeEscape(
const std::string& s,
size_t& index, std::string& res) {
172 if (index + 4 > s.length()) {
176 std::string hexStr = s.substr(index, 4);
178 unsigned int codePoint = std::stoul(hexStr,
nullptr, 16);
180 if (codePoint <= 0x7f) {
181 res +=
static_cast<char>(codePoint);
182 }
else if (codePoint <= 0x7ff) {
183 res +=
static_cast<char>(0xc0 | ((codePoint >> 6) & 0x1f));
184 res +=
static_cast<char>(0x80 | (codePoint & 0x3f));
186 res +=
static_cast<char>(0xe0 | ((codePoint >> 12) & 0x0f));
187 res +=
static_cast<char>(0x80 | ((codePoint >> 6) & 0x3f));
188 res +=
static_cast<char>(0x80 | (codePoint & 0x3f));
192 static JsonElement ParseString(
const std::string& s,
size_t& index) {
197 while (index < s.length()) {
205 if (index + 1 >= s.length()) {
206 throw JsonException(
"Unterminated escape sequence in string");
208 char escaped = s[index + 1];
212 case '\"': res +=
'\"';
break;
213 case '\\': res +=
'\\';
break;
214 case '/': res +=
'/';
break;
215 case 'b': res +=
'\b';
break;
216 case 'f': res +=
'\f';
break;
217 case 'n': res +=
'\n';
break;
218 case 'r': res +=
'\r';
break;
219 case 't': res +=
'\t';
break;
220 case 'u': ParseUnicodeEscape(s, index, res);
break;
222 throw JsonException((std::string(
"Unknown escape sequence: \\") + escaped).c_str());
233 static JsonElement ParseBool(
const std::string& s,
size_t& index) {
235 if (s.compare(index, 4,
"true") == 0) {
238 }
else if (s.compare(index, 5,
"false") == 0) {
245 static JsonElement ParseNull(
const std::string& s,
size_t& index) {
247 if (s.compare(index, 4,
"null") == 0) {
254 static JsonElement ParseNumber(
const std::string& s,
size_t& index) {
256 size_t start = index;
257 if (s[index] ==
'-') {
260 while (index < s.length() && (std::isdigit(
static_cast<unsigned char>(s[index])) || s[index] ==
'.' || s[index] ==
'e' || s[index] ==
'E' || s[index] ==
'+' || s[index] ==
'-')) {
263 std::string numStr = s.substr(start, index - start);
265 double val = std::stod(numStr);
267 }
catch (
const std::exception&) {
268 throw JsonException((
"Invalid number format: " + numStr).c_str());
285 if (objOther.m_pImpl) {
286 m_pImpl->eKind = objOther.m_pImpl->eKind;
287 m_pImpl->bBoolValue = objOther.m_pImpl->bBoolValue;
288 m_pImpl->dNumValue = objOther.m_pImpl->dNumValue;
289 m_pImpl->sStrValue = objOther.m_pImpl->sStrValue;
291 for (int i = 0; i < objOther.m_pImpl->lstArray.GetCount(); ++i) {
292 m_pImpl->lstArray.Add(objOther.m_pImpl->lstArray[i]);
295 auto keys = objOther.m_pImpl->dictObject.GetKeys();
296 for (
int i = 0; i < keys.GetLength(); ++i) {
297 m_pImpl->dictObject.Add(keys[i], objOther.m_pImpl->dictObject[keys[i]]);
304 if (
this != &objOther) {
306 if (objOther.m_pImpl) {
307 m_pImpl->eKind = objOther.m_pImpl->eKind;
308 m_pImpl->bBoolValue = objOther.m_pImpl->bBoolValue;
309 m_pImpl->dNumValue = objOther.m_pImpl->dNumValue;
310 m_pImpl->sStrValue = objOther.m_pImpl->sStrValue;
312 for (
int i = 0; i < objOther.m_pImpl->lstArray.GetCount(); ++i) {
313 m_pImpl->lstArray.Add(objOther.m_pImpl->lstArray[i]);
316 auto keys = objOther.m_pImpl->dictObject.GetKeys();
317 for (
int i = 0; i < keys.GetLength(); ++i) {
318 m_pImpl->dictObject.Add(keys[i], objOther.m_pImpl->dictObject[keys[i]]);
326 : m_pImpl(std::move(objOther.m_pImpl)) {
332 if (
this != &objOther) {
333 m_pImpl = std::move(objOther.m_pImpl);
346 m_pImpl->bBoolValue = bValue;
352 m_pImpl->dNumValue = dValue;
358 m_pImpl->sStrValue = sValue;
381 return m_pImpl->dNumValue;
391 return static_cast<long long>(
GetDouble());
397 return m_pImpl->sStrValue;
403 return m_pImpl->lstArray.GetCount();
409 return m_pImpl->lstArray[iIndex];
415 m_pImpl->lstArray.Add(objElement);
421 return m_pImpl->dictObject.TryGetValue(sPropertyName, objValue);
427 if (m_pImpl->dictObject.ContainsKey(sPropertyName)) {
428 m_pImpl->dictObject[sPropertyName] = objValue;
430 m_pImpl->dictObject.Add(sPropertyName, objValue);
437 return m_pImpl->dictObject.GetKeys();
442 std::string sRes =
"[";
443 for (
int i = 0; i < lstArray.
GetCount(); ++i) {
444 if (i > 0) sRes +=
",";
445 sRes += lstArray[i].ToString().GetRawString();
447 return String((sRes +
"]").c_str());
452 std::string sRes =
"{";
453 auto keys = dictObject.
GetKeys();
454 for (
int i = 0; i < keys.GetLength(); ++i) {
455 if (i > 0) sRes +=
",";
458 sRes += dictObject[keys[i]].ToString().GetRawString();
460 return String((sRes +
"}").c_str());
465 if (dVal ==
static_cast<long long>(dVal))
return String(std::to_string(
static_cast<long long>(dVal)).c_str());
467 snprintf(buf,
sizeof(buf),
"%g", dVal);
473 if (!m_pImpl)
return "null";
474 switch (m_pImpl->eKind) {
482 default:
return "null";
488 return JsonParser::Parse(sJson);
Defines the exception thrown when a method call is invalid for the object's current state.
Represents a specific JSON value within a JsonDocument.
Exception thrown when invalid JSON payload or token is encountered per RFC 8259.
Represents a strongly typed list of objects that can be accessed by index mirroring ....
Represents a mutable string of characters for efficient dynamic text composition.
Provides methods for creating, manipulating, searching, and sorting arrays, thereby serving as the ba...
Represents a collection of keys and values.
Array< TKey > GetKeys() const
Represents a strongly typed list of objects accessible by index.
int GetCount() const
Gets the number of elements contained in the List.
InvalidOperationException(const String &sMessage)
Initializes a new instance of the InvalidOperationException class with a specified error message.
A unified smart pointer that supports both unique and shared ownership semantics.
static SmartPointer< T > New()
Creates a new SmartPointer (default construction).
Represents text as a sequence of UTF-8 code units with culture-invariant operations.
String()
Initializes a new instance of the String class to an empty string.
const char * GetRawString() const
String GetString() const
Gets the value of the element as a string.
int GetArrayLength() const
Gets the number of values contained within the current JSON array value.
int GetInt32() const
Gets the current JSON number as a 32-bit signed integer.
Array< String > GetPropertyNames() const
Gets an array containing the names of all properties on the current JSON object.
JsonValueKind GetValueKind() const
Gets the type of the current JSON value.
JsonElement & operator=(const JsonElement &objOther)
bool TryGetProperty(const String &sPropertyName, JsonElement &objValue) const
Looks for a property named propertyName in the current JSON object.
String ToString() const
Serializes the element into a JSON string representation.
JsonElement GetArrayElement(int iIndex) const
Gets the value at the specified index in the current JSON array.
JsonElement()
Initializes a new instance of the JsonElement class representing undefined.
void AddArrayElement(const JsonElement &objElement)
Adds an element to the current JSON array.
long long GetInt64() const
Gets the current JSON number as a 64-bit signed integer.
bool GetBoolean() const
Gets the value of the element as a Boolean.
~JsonElement()
Destructor releasing element resources.
static JsonElement Parse(const String &sJson)
Parses text representing a single JSON value into a JsonElement.
void SetProperty(const String &sPropertyName, const JsonElement &objValue)
Sets or replaces a property on the current JSON object.
double GetDouble() const
Gets the current JSON number as a double.
JsonException()
Initializes a new instance of the JsonException class with a default message.
static String FormatJsonNumber(double dVal)
static String FormatJsonObject(const Collections::Generic::Dictionary< String, JsonElement > &dictObject)
static String EscapeString(const String &sInput)
JsonValueKind
Specifies the data type of a JSON value.
static String FormatJsonArray(const Collections::Generic::List< JsonElement > &lstArray)