I am implementing a json parser in C++. I have written some code and wanted to share it on Stack Overflow.
While writing this program I assumed that the json will only have objects and arrays are only string arrays.
Also I used a stack to find corresponding closing ']' or '}'.
I used vectors to store arrays so that I could get specific elements using their index.
Below is my code:
#include<iostream>
#include<stack>
#include<vector>
using namespace std;
class JsonHelper {
wstring json_wstr;
stack<wstring> wstack;
vector<wstring> v;
public:
JsonHelper(wstring input_json);
JsonHelper operator[](wstring wstr);
JsonHelper operator[](long index);
};
JsonHelper::JsonHelper(wstring input_json):json_wstr(input_json) {
//Validate Json Here
}
JsonHelper JsonHelper::operator [](std::wstring wstr){
if(json_wstr.empty()) {
throw L"Json Is Empty";
}
long pos = json_wstr.find(wstr);
if(pos == std::wstring::npos) {
throw L"Object not found in json";
}
pos = json_wstr.find(L":",pos);
pos++;
long last_pos = pos;
while(1){
if(json_wstr[pos]== L'}' && wstack.empty()) {
break;
}
if(json_wstr[pos] == L',' && wstack.empty()){
break;
}
if(json_wstr[pos] == L'{') {
wstack.push(L"{");
}
if(json_wstr[pos] == L'}'){
if(wstack.top().find(L"{") == wstring::npos)
throw L"Invalid Json";
wstack.pop();
}
if(json_wstr[pos] == L'[') {
wstack.push(L"[");
}
if(json_wstr[pos] == L']'){
if(wstack.top().find(L"[") == wstring::npos)
throw L"Invalid Json";
wstack.pop();
}
pos++;
}
wstring json_object = json_wstr.substr(last_pos,(pos-last_pos));
json_object.erase(json_object.find_last_not_of(L" \n\r\t")+1);
json_object.erase(0,json_object.find_first_not_of(L" \n\r\t"));
return JsonHelper(json_object);
}
JsonHelper JsonHelper::operator [](long index) {
wstring tmp;
if(json_wstr.empty()) {
throw L"Json Is Empty";
}
long pos = json_wstr.find_first_of(L"[");
if(pos == wstring::npos)
throw L"Invalid Json";
long last_pos = ++pos;
while(1) {
if(json_wstr[pos] == L',' && wstack.empty()) {
tmp = json_wstr.substr(last_pos,pos-last_pos);
tmp.erase(tmp.find_last_not_of(L" \n\r\t")+1);
tmp.erase(0,tmp.find_first_not_of(L" \n\r\t"));
v.push_back(tmp);
last_pos= pos+1;
}
if(json_wstr[pos] == L'{') {
wstack.push(L"{");
}
if(json_wstr[pos] == L'}'){
if(wstack.top().find(L"{") == wstring::npos)
throw L"Invalid Json";
wstack.pop();
}
if(json_wstr[pos] == L'[') {
wstack.push(L"[");
}
if(json_wstr[pos] == L']' && wstack.empty()) {
tmp = json_wstr.substr(last_pos,pos-last_pos);
tmp.erase(tmp.find_last_not_of(L" \n\r\t")+1);
tmp.erase(0,tmp.find_first_not_of(L" \n\r\t"));
v.push_back(tmp);
break;
}
if(json_wstr[pos] == L']'){
if(wstack.top().find(L"[") == wstring::npos)
throw L"Invalid Json";
wstack.pop();
}
pos++;
}
if(v.size() == 0) {
throw "Invalid Array object or array is empty";
}
return v.at(index-1);
}
int main() {
JsonHelper j(L"{\"ID\": \"SGML\",\"SortAs\": \"SGML\",\"GlossTerm\": \"Standard Generalized Markup Language\",\"Acronym\": \"SGML\",\"Abbrev\": \"ISO 8879:1986\",\"GlossDef\": {\"para\": \"A meta-markup language, used to create markup languages such as DocBook.\",\"GlossSeeAlso\": [\"XML\", \"GML\"]},\"GlossSee\": \"markup\"}");
JsonHelper j1 = j[L"GlossDef"][L"GlossSeeAlso"][2];
return 0;
}
Please suggest improvements for my code. A few improvements I am looking for are
- Validate the Json, I am thinking of using regx in c++
- Get a specific value like Float, Bool, String etc.
- Improved Performance
- Should be able to handle huge json