http 请求时,经常需要读取 json,于是我自己写了一个轻量级的 O ( n 2 ) O(n^2) O(n2) json 解析。(只读,不修改)
原理很简单,递归建树即可。
性能一般般,不过一般的 http 请求很够用了
#include<bits/stdc++.h>
using namespace std;
struct Json {
int type;
/*
1 数据
2 []
3 {}
*/
string dat;
vector<string>name;
vector<Json>child;
void output(int dep=0) {
for(int i=0; i<dep; i++) putchar(' ');
if(type == 1) printf("%s\n",dat.c_str());
else if(type == 2) {
printf("[\n");
for(int i=0; i<child.size(); i++) child[i].output(dep+2);
for(int i=0; i<dep; i++) putchar(' ');
printf("]\n");
} else if(type == 3) {
printf("{\n");
for(int i=0; i<child.size(); i++) {
for(int i=0; i<dep; i++) putchar(' ');
// 如果键值对是字符串,就显示在一行,否则分多行显示
if(child[i].type == 1) printf(" %s: %s\n",name[i].c_str(),child[i].dat.c_str());
else printf(" %s: \n",name[i].c_str()), child[i].output(dep+2);
}
for(int i=0; i<dep; i++) putchar(' ');
printf("}\n");
}
}
Json & operator [] (string s) {
if(type==3)
for(int i=0; i<name.size(); i++)
if(name[i] == s)
return child[i];
}
inline Json & operator [] (int i) {
if(type==2) return child[i];
}
inline int asint() {
return stoi(dat);
}
inline int size() {
return child.size();
}
};
Json dfs(string s, int l, int r) { // O(n^2) 的构造,不过一般的 json 够用了
Json retval;
int type=1;
bool in_str=0;
if(s[l] == '[') type=2;
else if(s[l] == '{') type=3;
if(type == 1) {
if(s[l]=='"' && s[r]=='"') ++l,--r; // 删除双引号
retval.dat = s.substr(l, r-l+1);
retval.type = 1;
} else if(type == 2) {
int last=l+1, cnt=0, empty=1;
for(int i=l+1; i<r; i++) {
if(s[i]!=' ') empty=0;
if(s[i]=='"') in_str=!in_str;
if(!in_str) {
if(s[i]=='[' || s[i]=='{') cnt++;
else if(s[i]==']' || s[i]=='}') cnt--;
if(cnt==0 && s[i]==',') retval.child.push_back(dfs(s,last,i-1)), last=i+1;
}
}
if(!empty) retval.child.push_back(dfs(s,last,r-1));
retval.type = 2;
} else if(type == 3) {
int last=l+1, cnt=0, empty=1;
for(int i=l+1; i<r; i++) {
if(s[i]!=' ') empty=0;
if(s[i]=='"') in_str=!in_str;
if(!in_str) {
if(s[i]==' ') continue;
else if(s[i]=='[' || s[i]=='{') cnt++;
else if(s[i]==']' || s[i]=='}') cnt--;
if(cnt==0 && s[i]==':') {
if(s[last]=='"' && s[i-1]=='"') retval.name.push_back(s.substr(last+1, i-last-2)); // 删除双引号
else retval.name.push_back(s.substr(last, i-last));
last=i+1;
} else if(cnt==0 && s[i]==',') retval.child.push_back(dfs(s,last,i-1)), last=i+1;
}
}
if(!empty) retval.child.push_back(dfs(s,last,r-1));
retval.type = 3;
}
return retval;
}
Json Tojson(string s) {
int in_str=0;
string s2; // 去除多余空格
for(int i=0; i<s.size(); i++) {
if(s[i]=='"') in_str=!in_str;
else if(in_str || (s[i]!=32 && s[i]!=9 && s[i]!=10 && s[i]!=13)) s2+=s[i];
}
return dfs(s2,0,s2.size()-1);
}
int main() {
// 以字符串构造。必须保证json格式正确(空格没关系)
Json test = Tojson("{a:114514, b:\"abc\"}");
// 访问子节点
Json child = test["a"];
// 转换为 int
cout << child.asint() << endl;
// 直接获取 string 类型的数据
cout << child.dat << endl;
return 0;
}