2026-08-28 11:16:09 -05:00 | | | #ifndef __CJSONNODE_MQH__
|
| | | #define __CJSONNODE_MQH__
|
| | |
|
| | | // Nota el autor original pasaba todos los strigns como copia lo cambia a const string& (text) para que sea mas justo..
|
| | | // https://www.mql5.com/en/articles/16791
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| CJsonNode.mqh - A Minimalistic JSON Parser & Serializer in MQL5 |
|
| | | //| Feel free to adapt as needed. |
|
| | | //+------------------------------------------------------------------+
|
| | | #property strict
|
| | |
|
| | | //--- Enumeration of possible JSON node types
|
| | | enum JsonNodeType
|
| | | {
|
| | | JSON_UNDEF = 0,
|
| | | JSON_OBJ,
|
| | | JSON_ARRAY,
|
| | | JSON_STRING,
|
| | | JSON_NUMBER,
|
| | | JSON_BOOL,
|
| | | JSON_NULL
|
| | | };
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Class representing a single JSON node |
|
| | | //+------------------------------------------------------------------
|
| | | class CJsonNode
|
| | | {
|
| | | public:
|
| | | //--- Constructor & Destructor
|
| | | CJsonNode();
|
| | | ~CJsonNode();
|
| | |
|
| | | //---
|
| | | string __bjson; // json a parsear..
|
| | |
|
| | | //--- Parse entire JSON text
|
| | | bool ParseString();
|
| | |
|
| | | //--- Check if node is valid
|
| | | bool IsValid();
|
| | |
|
| | | //--- Get potential error message if not valid
|
| | | string GetErrorMsg();
|
| | |
|
| | | //--- Access node type
|
| | | JsonNodeType GetType();
|
| | |
|
| | | //--- For arrays
|
| | | int ChildCount();
|
| | |
|
| | | //--- For objects: get child by key
|
| | | CJsonNode* GetChild(string key);
|
| | |
|
| | | //--- For arrays: get child by index
|
| | | CJsonNode* GetChild(int index);
|
| | |
|
| | | //--- Convert to string / number / bool
|
| | | string AsString();
|
| | | double AsNumber();
|
| | | bool AsBool();
|
| | |
|
| | | //--- Serialize back to JSON
|
| | | string ToJsonString();
|
| | |
|
| | | int GetKeys(string &out_keys[]);
|
| | |
|
| | | private:
|
| | | //--- Data members
|
| | | JsonNodeType m_type; // Type of this node (object, array, etc.)
|
| | | string m_value; // For storing string content if node is string
|
| | | double m_numVal; // For numeric values
|
| | | bool m_boolVal; // For boolean values
|
| | | CJsonNode m_children[]; // Child nodes (for objects and arrays)
|
| | | string m_keys[]; // Keys for child nodes (valid if JSON_OBJ)
|
| | | bool m_valid; // True if node is validly parsed
|
| | | string m_errMsg; // Optional error message for debugging
|
| | |
|
| | | //--- Internal methods
|
| | | void Reset();
|
| | | bool ParseValue(const string& text,int &pos);
|
| | | bool ParseObject(const string& text,int &pos);
|
| | | bool ParseArray(const string& text,int &pos);
|
| | | bool ParseNumber(const string& text,int &pos);
|
| | | bool ParseStringLiteral(const string& text,int &pos);
|
| | | bool ParseKeyLiteral(const string& text,int &pos,string &keyOut);
|
| | | string UnescapeString(const string& input_);
|
| | | bool SkipWhitespace(const string& text,int &pos);
|
| | | bool AllWhitespace(const string& text,int pos);
|
| | | string SerializeNode();
|
| | | string SerializeObject();
|
| | | string SerializeArray();
|
| | | string EscapeString(const string& s);
|
| | | };
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Constructor |
|
| | | //+------------------------------------------------------------------
|
| | | CJsonNode::CJsonNode()
|
| | | {
|
| | | m_type = JSON_UNDEF;
|
| | | m_value = "";
|
| | | m_numVal = 0.0;
|
| | | m_boolVal = false;
|
| | | m_valid = true;
|
| | | ArrayResize(m_children,0);
|
| | | ArrayResize(m_keys,0);
|
| | | m_errMsg = "";
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Destructor |
|
| | | //+------------------------------------------------------------------
|
| | | CJsonNode::~CJsonNode()
|
| | | {
|
| | | // No dynamic pointers to free; arrays are handled by MQL itself
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Parse entire JSON text |
|
| | | //+------------------------------------------------------------------
|
| | | bool CJsonNode::ParseString()
|
| | | {
|
| | | Reset();
|
| | | int pos = 0;
|
| | | bool res = (ParseValue(__bjson,pos) && SkipWhitespace(__bjson,pos));
|
| | |
|
| | | // If there's leftover text that's not whitespace, it's an error
|
| | | if(pos < StringLen(__bjson))
|
| | | {
|
| | | if(!AllWhitespace(__bjson,pos))
|
| | | {
|
| | | m_valid = false;
|
| | | m_errMsg = "Extra data after JSON parsing.";
|
| | | res = false;
|
| | | }
|
| | | }
|
| | | return (res && m_valid);
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Check if node is valid |
|
| | | //+------------------------------------------------------------------
|
| | | bool CJsonNode::IsValid()
|
| | | {
|
| | | return m_valid;
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Get potential error message if not valid |
|
| | | //+------------------------------------------------------------------
|
| | | string CJsonNode::GetErrorMsg()
|
| | | {
|
| | | return m_errMsg;
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Access node type |
|
| | | //+------------------------------------------------------------------
|
| | | JsonNodeType CJsonNode::GetType()
|
| | | {
|
| | | return m_type;
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| For arrays: get number of children |
|
| | | //+------------------------------------------------------------------
|
| | | int CJsonNode::ChildCount()
|
| | | {
|
| | | return ArraySize(m_children);
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| For objects: get child by key |
|
| | | //+------------------------------------------------------------------
|
| | | CJsonNode* CJsonNode::GetChild(string key)
|
| | | {
|
| | | if(m_type != JSON_OBJ)
|
| | | return NULL;
|
| | | for(int i=0; i<ArraySize(m_keys); i++)
|
| | | {
|
| | | if(m_keys[i] == key)
|
| | | return &m_children[i];
|
| | | }
|
| | | return NULL;
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| For arrays: get child by index |
|
| | | //+------------------------------------------------------------------
|
| | | CJsonNode* CJsonNode::GetChild(int index)
|
| | | {
|
| | | if(m_type != JSON_ARRAY)
|
| | | return NULL;
|
| | | if(index<0 || index>=ArraySize(m_children))
|
| | | return NULL;
|
| | | return &m_children[index];
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Convert to string / number / bool |
|
| | | //+------------------------------------------------------------------
|
| | | string CJsonNode::AsString()
|
| | | {
|
| | | if(m_type == JSON_STRING) return m_value;
|
| | | if(m_type == JSON_NUMBER) return DoubleToString(m_numVal,8);
|
| | | if(m_type == JSON_BOOL) return m_boolVal ? "true" : "false";
|
| | | if(m_type == JSON_NULL) return "null";
|
| | | // For object/array/undefined, return empty or handle as needed
|
| | | return "";
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Convert node to numeric |
|
| | | //+------------------------------------------------------------------
|
| | | double CJsonNode::AsNumber()
|
| | | {
|
| | | if(m_type == JSON_NUMBER) return m_numVal;
|
| | | // If bool, return 1 or 0
|
| | | if(m_type == JSON_BOOL) return (m_boolVal ? 1.0 : 0.0);
|
| | | return 0.0;
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Convert node to boolean |
|
| | | //+------------------------------------------------------------------
|
| | | bool CJsonNode::AsBool()
|
| | | {
|
| | | if(m_type == JSON_BOOL) return m_boolVal;
|
| | | if(m_type == JSON_NUMBER) return (m_numVal != 0.0);
|
| | | if(m_type == JSON_STRING) return (StringLen(m_value) > 0);
|
| | | return false;
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Serialize node back to JSON |
|
| | | //+------------------------------------------------------------------
|
| | | string CJsonNode::ToJsonString()
|
| | | {
|
| | | return SerializeNode();
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Reset node to initial state |
|
| | | //+------------------------------------------------------------------
|
| | | void CJsonNode::Reset()
|
| | | {
|
| | | m_type = JSON_UNDEF;
|
| | | m_value = "";
|
| | | m_numVal = 0.0;
|
| | | m_boolVal = false;
|
| | | m_valid = true;
|
| | | ArrayResize(m_children,0);
|
| | | ArrayResize(m_keys,0);
|
| | | m_errMsg = "";
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Dispatch parse based on first character |
|
| | | //+------------------------------------------------------------------
|
| | | bool CJsonNode::ParseValue(const string& text,int &pos)
|
| | | {
|
| | | if(!SkipWhitespace(text,pos)) return false;
|
| | | if(pos >= StringLen(text)) return false;
|
| | |
|
| | | string c = StringSubstr(text,pos,1);
|
| | |
|
| | | //--- Object
|
| | | if(c == "{")
|
| | | return ParseObject(text,pos);
|
| | |
|
| | | //--- Array
|
| | | if(c == "[")
|
| | | return ParseArray(text,pos);
|
| | |
|
| | | //--- String
|
| | | if(c == "\"")
|
| | | return ParseStringLiteral(text,pos);
|
| | |
|
| | | //--- Boolean / null
|
| | | if(StringSubstr(text,pos,4) == "true")
|
| | | {
|
| | | m_type = JSON_BOOL;
|
| | | m_boolVal = true;
|
| | | pos += 4;
|
| | | return true;
|
| | | }
|
| | | if(StringSubstr(text,pos,5) == "false")
|
| | | {
|
| | | m_type = JSON_BOOL;
|
| | | m_boolVal = false;
|
| | | pos += 5;
|
| | | return true;
|
| | | }
|
| | | if(StringSubstr(text,pos,4) == "null")
|
| | | {
|
| | | m_type = JSON_NULL;
|
| | | pos += 4;
|
| | | return true;
|
| | | }
|
| | |
|
| | | //--- Otherwise, parse number
|
| | | return ParseNumber(text,pos);
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Parse object: { ... } |
|
| | | //+------------------------------------------------------------------
|
| | | bool CJsonNode::ParseObject(const string& text,int &pos)
|
| | | {
|
| | | m_type = JSON_OBJ;
|
| | | pos++; // skip '{'
|
| | | if(!SkipWhitespace(text,pos)) return false;
|
| | |
|
| | | //--- Check for empty object
|
| | | if(pos < StringLen(text) && StringSubstr(text,pos,1) == "}")
|
| | | {
|
| | | pos++;
|
| | | return true;
|
| | | }
|
| | |
|
| | | //--- Parse key-value pairs
|
| | | while(pos < StringLen(text))
|
| | | {
|
| | | if(!SkipWhitespace(text,pos)) return false;
|
| | |
|
| | | // Expect key in quotes
|
| | | if(pos >= StringLen(text) || StringSubstr(text,pos,1) != "\"")
|
| | | {
|
| | | m_valid = false;
|
| | | m_errMsg = "Object key must start with double quote.";
|
| | | return false;
|
| | | }
|
| | |
|
| | | string key = "";
|
| | | if(!ParseKeyLiteral(text,pos,key))
|
| | | return false;
|
| | |
|
| | | if(!SkipWhitespace(text,pos)) return false;
|
| | | // Expect a colon
|
| | | if(pos >= StringLen(text) || StringSubstr(text,pos,1) != ":")
|
| | | {
|
| | | m_valid = false;
|
| | | m_errMsg = "Missing colon after object key.";
|
| | | return false;
|
| | | }
|
| | | pos++; // skip ':'
|
| | | if(!SkipWhitespace(text,pos)) return false;
|
| | |
|
| | | // Parse the child value
|
| | | CJsonNode child;
|
| | | if(!child.ParseValue(text,pos))
|
| | | {
|
| | | m_valid = false;
|
| | | m_errMsg = "Failed to parse object value.";
|
| | | return false;
|
| | | }
|
| | |
|
| | | // Store
|
| | | int idx = ArraySize(m_children);
|
| | | ArrayResize(m_children,idx+1);
|
| | | ArrayResize(m_keys,idx+1);
|
| | | m_children[idx] = child;
|
| | | m_keys[idx] = key;
|
| | |
|
| | | if(!SkipWhitespace(text,pos)) return false;
|
| | | if(pos >= StringLen(text)) return false;
|
| | |
|
| | | string nextC = StringSubstr(text,pos,1);
|
| | | if(nextC == "}")
|
| | | {
|
| | | pos++;
|
| | | return true;
|
| | | }
|
| | | if(nextC != ",")
|
| | | {
|
| | | m_valid = false;
|
| | | m_errMsg = "Missing comma in object.";
|
| | | return false;
|
| | | }
|
| | | pos++; // skip comma
|
| | | }
|
| | |
|
| | | return false; // didn't see closing '}'
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Parse array: [ ... ] |
|
| | | //+------------------------------------------------------------------
|
| | | bool CJsonNode::ParseArray(const string& text,int &pos)
|
| | | {
|
| | | m_type = JSON_ARRAY;
|
| | | pos++; // skip '['
|
| | | if(!SkipWhitespace(text,pos)) return false;
|
| | |
|
| | | //--- Check for empty array
|
| | | if(pos < StringLen(text) && StringSubstr(text,pos,1) == "]")
|
| | | {
|
| | | pos++;
|
| | | return true;
|
| | | }
|
| | |
|
| | | //--- Parse elements
|
| | | while(pos < StringLen(text))
|
| | | {
|
| | | CJsonNode child;
|
| | | if(!child.ParseValue(text,pos))
|
| | | {
|
| | | m_valid = false;
|
| | | m_errMsg = "Failed to parse array element.";
|
| | | return false;
|
| | | }
|
| | | int idx = ArraySize(m_children);
|
| | | ArrayResize(m_children,idx+1);
|
| | | m_children[idx] = child;
|
| | |
|
| | | if(!SkipWhitespace(text,pos)) return false;
|
| | | if(pos >= StringLen(text)) return false;
|
| | |
|
| | | string nextC = StringSubstr(text,pos,1);
|
| | | if(nextC == "]")
|
| | | {
|
| | | pos++;
|
| | | return true;
|
| | | }
|
| | | if(nextC != ",")
|
| | | {
|
| | | m_valid = false;
|
| | | m_errMsg = "Missing comma in array.";
|
| | | return false;
|
| | | }
|
| | | pos++; // skip comma
|
| | | if(!SkipWhitespace(text,pos)) return false;
|
| | | }
|
| | |
|
| | | return false; // didn't see closing ']'
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Parse a numeric value |
|
| | | //+------------------------------------------------------------------
|
| | | bool CJsonNode::ParseNumber(const string& text,int &pos)
|
| | | {
|
| | | m_type = JSON_NUMBER;
|
| | | int startPos = pos;
|
| | |
|
| | | // Scan allowed chars in a JSON number
|
| | | while(pos < StringLen(text))
|
| | | {
|
| | | string c = StringSubstr(text,pos,1);
|
| | | if(c=="-" || c=="+" || c=="." || c=="e" || c=="E" || (c>="0" && c<="9"))
|
| | | pos++;
|
| | | else
|
| | | break;
|
| | | }
|
| | |
|
| | | string numStr = StringSubstr(text,startPos,pos - startPos);
|
| | | if(StringLen(numStr) == 0)
|
| | | {
|
| | | m_valid = false;
|
| | | m_errMsg = "Expected number, found empty.";
|
| | | return false;
|
| | | }
|
| | |
|
| | | m_numVal = StringToDouble(numStr);
|
| | | return true;
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Parse a string literal (leading quote already checked) |
|
| | | //+------------------------------------------------------------------
|
| | | bool CJsonNode::ParseStringLiteral(const string& text,int &pos)
|
| | | {
|
| | | pos++; // skip leading quote
|
| | | string result = "";
|
| | |
|
| | | while(pos < StringLen(text))
|
| | | {
|
| | | string c = StringSubstr(text,pos,1);
|
| | | if(c == "\"")
|
| | | {
|
| | | // closing quote
|
| | | pos++;
|
| | | m_type = JSON_STRING;
|
| | | m_value = UnescapeString(result);
|
| | | return true;
|
| | | }
|
| | | if(c == "\\")
|
| | | {
|
| | | // handle escape
|
| | | pos++;
|
| | | if(pos >= StringLen(text))
|
| | | break;
|
| | | string ec = StringSubstr(text,pos,1);
|
| | | result += ("\\" + ec); // accumulate, we'll decode later
|
| | | pos++;
|
| | | }
|
| | | else
|
| | | {
|
| | | result += c;
|
| | | pos++;
|
| | | }
|
| | | }
|
| | |
|
| | | // If we get here, string was not closed
|
| | | m_valid = false;
|
| | | m_errMsg = "Unclosed string literal.";
|
| | | return false;
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Parse a string key (similar to a literal) |
|
| | | //+------------------------------------------------------------------
|
| | | bool CJsonNode::ParseKeyLiteral(const string& text,int &pos,string &keyOut)
|
| | | {
|
| | | pos++; // skip leading quote
|
| | | string buffer = "";
|
| | |
|
| | | while(pos < StringLen(text))
|
| | | {
|
| | | string c = StringSubstr(text,pos,1);
|
| | | if(c == "\"")
|
| | | {
|
| | | pos++;
|
| | | keyOut = UnescapeString(buffer);
|
| | | return true;
|
| | | }
|
| | | if(c == "\\")
|
| | | {
|
| | | pos++;
|
| | | if(pos >= StringLen(text))
|
| | | break;
|
| | | string ec = StringSubstr(text,pos,1);
|
| | | buffer += ("\\" + ec);
|
| | | pos++;
|
| | | }
|
| | | else
|
| | | {
|
| | | buffer += c;
|
| | | pos++;
|
| | | }
|
| | | }
|
| | |
|
| | | m_valid = false;
|
| | | m_errMsg = "Unclosed key string.";
|
| | | return false;
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Unescape sequences like \" \\ \n etc. |
|
| | | //+------------------------------------------------------------------
|
| | | string CJsonNode::UnescapeString(const string& input_)
|
| | | {
|
| | | string out = "";
|
| | | int i = 0;
|
| | |
|
| | | while(i < StringLen(input_))
|
| | | {
|
| | | string c = StringSubstr(input_,i,1);
|
| | | if(c == "\\")
|
| | | {
|
| | | i++;
|
| | | if(i >= StringLen(input_))
|
| | | {
|
| | | // Single backslash at end
|
| | | out += "\\";
|
| | | break;
|
| | | }
|
| | | string ec = StringSubstr(input_,i,1);
|
| | |
|
| | | if(ec == "\"") out += "\"";
|
| | | else if(ec == "\\") out += "\\";
|
| | | else if(ec == "n") out += "\n";
|
| | | else if(ec == "r") out += "\r";
|
| | | else if(ec == "t") out += "\t";
|
| | | else if(ec == "b") out += CharToString(8); // ASCII backspace
|
| | | else if(ec == "f") out += CharToString(12); // ASCII formfeed
|
| | | else out += ("\\" + ec);
|
| | |
|
| | | i++;
|
| | | }
|
| | | else
|
| | | {
|
| | | out += c;
|
| | | i++;
|
| | | }
|
| | | }
|
| | | return out;
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Skip whitespace |
|
| | | //+------------------------------------------------------------------
|
| | | bool CJsonNode::SkipWhitespace(const string& text,int &pos)
|
| | | {
|
| | | while(pos < StringLen(text))
|
| | | {
|
| | | ushort c = StringGetCharacter(text,pos);
|
| | | if(c == ' ' || c == '\t' || c == '\n' || c == '\r')
|
| | | pos++;
|
| | | else
|
| | | break;
|
| | | }
|
| | | // Return true if we haven't gone beyond string length
|
| | | return (pos <= StringLen(text));
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Check if remainder is all whitespace |
|
| | | //+------------------------------------------------------------------
|
| | | bool CJsonNode::AllWhitespace(const string& text,int pos)
|
| | | {
|
| | | while(pos < StringLen(text))
|
| | | {
|
| | | ushort c = StringGetCharacter(text,pos);
|
| | | if(c != ' ' && c != '\t' && c != '\n' && c != '\r')
|
| | | return false;
|
| | | pos++;
|
| | | }
|
| | | return true;
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Serialization dispatcher |
|
| | | //+------------------------------------------------------------------
|
| | | string CJsonNode::SerializeNode()
|
| | | {
|
| | | switch(m_type)
|
| | | {
|
| | | case JSON_OBJ: return SerializeObject();
|
| | | case JSON_ARRAY: return SerializeArray();
|
| | | case JSON_STRING: return "\""+EscapeString(m_value)+"\"";
|
| | | case JSON_NUMBER: return DoubleToString(m_numVal,8);
|
| | | case JSON_BOOL: return (m_boolVal ? "true" : "false");
|
| | | case JSON_NULL: return "null";
|
| | | default: return "\"\""; // undefined => empty string
|
| | | }
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Serialize object |
|
| | | //+------------------------------------------------------------------
|
| | | string CJsonNode::SerializeObject()
|
| | | {
|
| | | string out = "{";
|
| | | for(int i=0; i<ArraySize(m_children); i++)
|
| | | {
|
| | | if(i > 0) out += ",";
|
| | | out += "\""+EscapeString(m_keys[i])+"\":";
|
| | | out += m_children[i].SerializeNode();
|
| | | }
|
| | | out += "}";
|
| | | return out;
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Serialize array |
|
| | | //+------------------------------------------------------------------
|
| | | string CJsonNode::SerializeArray()
|
| | | {
|
| | | string out = "[";
|
| | | for(int i=0; i<ArraySize(m_children); i++)
|
| | | {
|
| | | if(i > 0) out += ",";
|
| | | out += m_children[i].SerializeNode();
|
| | | }
|
| | | out += "]";
|
| | | return out;
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Escape a string for JSON output (backslashes, quotes, etc.) |
|
| | | //+------------------------------------------------------------------
|
| | | string CJsonNode::EscapeString(const string& s)
|
| | | {
|
| | | string out = "";
|
| | | for(int i=0; i<StringLen(s); i++)
|
| | | {
|
| | | ushort c = StringGetCharacter(s,i);
|
| | | switch(c)
|
| | | {
|
| | | case 34: // '"'
|
| | | out += "\\\"";
|
| | | break;
|
| | | case 92: // '\\'
|
| | | out += "\\\\";
|
| | | break;
|
| | | case 10: // '\n'
|
| | | out += "\\n";
|
| | | break;
|
| | | case 13: // '\r'
|
| | | out += "\\r";
|
| | | break;
|
| | | case 9: // '\t'
|
| | | out += "\\t";
|
| | | break;
|
| | | case 8: // backspace
|
| | | out += "\\b";
|
| | | break;
|
| | | case 12: // formfeed
|
| | | out += "\\f";
|
| | | break;
|
| | | default:
|
| | | // Directly append character
|
| | | out += ShortToString(c);
|
| | | break;
|
| | | }
|
| | | }
|
| | | return out;
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | // Agregado
|
| | | int CJsonNode::GetKeys(string &out_keys[])
|
| | | {
|
| | | if(m_type != JSON_OBJ) { ArrayResize(out_keys, 0); return 0; }
|
| | | int n = ArraySize(m_keys);
|
| | | ArrayResize(out_keys, n);
|
| | | for(int i = 0; i < n; i++) out_keys[i] = m_keys[i];
|
| | | return n;
|
| | | }
|
| | |
|
| | | #endif // __CJSONNODE_MQH__
|