C++编写Json数据解析的代码
时间: 2024-04-30 21:19:52 浏览: 128
以下是一个简单的C++ JSON解析器的示例代码:
```c++
#include <iostream>
#include <string>
#include <vector>
#include <map>
using namespace std;
enum JsonValueType {
JSON_NULL,
JSON_BOOLEAN,
JSON_NUMBER,
JSON_STRING,
JSON_ARRAY,
JSON_OBJECT
};
class JsonValue {
public:
JsonValueType type;
JsonValue() : type(JSON_NULL) {}
virtual ~JsonValue() {}
virtual void print(int depth = 0) const = 0;
};
class JsonNull : public JsonValue {
public:
JsonNull() { type = JSON_NULL; }
void print(int depth = 0) const override {
cout << "null";
}
};
class JsonBoolean : public JsonValue {
public:
bool value;
JsonBoolean(bool v) : value(v) { type = JSON_BOOLEAN; }
void print(int depth = 0) const override {
cout << (value ? "true" : "false");
}
};
class JsonNumber : public JsonValue {
public:
double value;
JsonNumber(double v) : value(v) { type = JSON_NUMBER; }
void print(int depth = 0) const override {
cout << value;
}
};
class JsonString : public JsonValue {
public:
string value;
JsonString(const string &v) : value(v) { type = JSON_STRING; }
void print(int depth = 0) const override {
cout << "\"" << value << "\"";
}
};
class JsonArray : public JsonValue {
public:
vector<JsonValue *> elements;
JsonArray() { type = JSON_ARRAY; }
~JsonArray() {
for (auto &element : elements) {
delete element;
}
}
void print(int depth = 0) const override {
cout << "[" << endl;
for (auto &element : elements) {
for (int i = 0; i < depth + 1; i++) {
cout << " ";
}
element->print(depth + 1);
if (element != elements.back()) {
cout << ",";
}
cout << endl;
}
for (int i = 0; i < depth; i++) {
cout << " ";
}
cout << "]";
}
};
class JsonObject : public JsonValue {
public:
map<string, JsonValue *> members;
JsonObject() { type = JSON_OBJECT; }
~JsonObject() {
for (auto &member : members) {
delete member.second;
}
}
void print(int depth = 0) const override {
cout << "{" << endl;
for (auto &member : members) {
for (int i = 0; i < depth + 1; i++) {
cout << " ";
}
cout << "\"" << member.first << "\": ";
member.second->print(depth + 1);
if (&member != &members.back()) {
cout << ",";
}
cout << endl;
}
for (int i = 0; i < depth; i++) {
cout << " ";
}
cout << "}";
}
};
class JsonParser {
public:
string json;
JsonParser(const string &json) : json(json) {}
JsonValue *parse() {
skipWhitespace();
if (json.empty()) {
return nullptr;
}
char c = json[0];
switch (c) {
case '{':
return parseObject();
case '[':
return parseArray();
case '\"':
return parseString();
case 't': {
string expect = "true";
if (json.substr(0, expect.size()) == expect) {
json = json.substr(expect.size());
return new JsonBoolean(true);
}
break;
}
case 'f': {
string expect = "false";
if (json.substr(0, expect.size()) == expect) {
json = json.substr(expect.size());
return new JsonBoolean(false);
}
break;
}
case 'n': {
string expect = "null";
if (json.substr(0, expect.size()) == expect) {
json = json.substr(expect.size());
return new JsonNull();
}
break;
}
default: {
if (c == '-' || (c >= '0' && c <= '9')) {
return parseNumber();
}
break;
}
}
throw runtime_error("Parse error");
}
private:
void skipWhitespace() {
while (!json.empty() && isspace(json[0])) {
json = json.substr(1);
}
}
JsonValue *parseObject() {
JsonObject *object = new JsonObject();
json = json.substr(1);
skipWhitespace();
while (json[0] != '}') {
if (json[0] != '\"') {
throw runtime_error("Parse error: Expected \"");
}
string key = parseString()->value;
skipWhitespace();
if (json[0] != ':') {
throw runtime_error("Parse error: Expected :");
}
json = json.substr(1);
skipWhitespace();
JsonValue *value = parse();
object->members[key] = value;
skipWhitespace();
if (json[0] == ',') {
json = json.substr(1);
skipWhitespace();
} else if (json[0] != '}') {
throw runtime_error("Parse error: Expected , or }");
}
}
json = json.substr(1);
return object;
}
JsonValue *parseArray() {
JsonArray *array = new JsonArray();
json = json.substr(1);
skipWhitespace();
while (json[0] != ']') {
JsonValue *value = parse();
array->elements.push_back(value);
skipWhitespace();
if (json[0] == ',') {
json = json.substr(1);
skipWhitespace();
} else if (json[0] != ']') {
throw runtime_error("Parse error: Expected , or ]");
}
}
json = json.substr(1);
return array;
}
JsonValue *parseString() {
string value;
json = json.substr(1);
while (true) {
if (json.empty()) {
throw runtime_error("Parse error: Expected \"");
}
char c = json[0];
json = json.substr(1);
if (c == '\"') {
return new JsonString(value);
} else if (c == '\\') {
if (json.empty()) {
throw runtime_error("Parse error: Expected escaped character");
}
char escape = json[0];
json = json.substr(1);
switch (escape) {
case '\"':
case '\\':
case '/':
value += escape;
break;
case 'b':
value += '\b';
break;
case 'f':
value += '\f';
break;
case 'n':
value += '\n';
break;
case 'r':
value += '\r';
break;
case 't':
value += '\t';
break;
case 'u': {
if (json.size() < 4) {
throw runtime_error("Parse error: Expected four hexadecimal digits");
}
string hex = json.substr(0, 4);
json = json.substr(4);
for (int i = 0; i < hex.size(); i++) {
if (!isxdigit(hex[i])) {
throw runtime_error("Parse error: Expected hexadecimal digit");
}
}
int codepoint = stoi(hex, nullptr, 16);
if (codepoint < 0 || codepoint > 0x10ffff ||
(codepoint >= 0xd800 && codepoint <= 0xdfff)) {
throw runtime_error("Parse error: Invalid Unicode code point");
}
if (codepoint < 0x80) {
value += static_cast<char>(codepoint);
} else if (codepoint < 0x800) {
value += static_cast<char>((codepoint >> 6) | 0xc0);
value += static_cast<char>((codepoint & 0x3f) | 0x80);
} else if (codepoint < 0x10000) {
value += static_cast<char>((codepoint >> 12) | 0xe0);
value += static_cast<char>(((codepoint >> 6) & 0x3f) | 0x80);
value += static_cast<char>((codepoint & 0x3f) | 0x80);
} else {
value += static_cast<char>((codepoint >> 18) | 0xf0);
value += static_cast<char>(((codepoint >> 12) & 0x3f) | 0x80);
value += static_cast<char>(((codepoint >> 6) & 0x3f) | 0x80);
value += static_cast<char>((codepoint & 0x3f) | 0x80);
}
break;
}
default:
throw runtime_error("Parse error: Invalid escape character");
}
} else {
value += c;
}
}
}
JsonValue *parseNumber() {
bool negative = false;
if (json[0] == '-') {
negative = true;
json = json.substr(1);
}
if (json.empty() || !isdigit(json[0])) {
throw runtime_error("Parse error: Expected digit");
}
double value = 0;
while (!json.empty() && isdigit(json[0])) {
value = value * 10 + (json[0] - '0');
json = json.substr(1);
}
if (!json.empty() && json[0] == '.') {
json = json.substr(1);
double fraction = 0.1;
while (!json.empty() && isdigit(json[0])) {
value += fraction * (json[0] - '0');
fraction *= 0.1;
json = json.substr(1);
}
}
if (!json.empty() && (json[0] == 'e' || json[0] == 'E')) {
json = json.substr(1);
bool exponent_negative = false;
if (json[0] == '-') {
exponent_negative = true;
json = json.substr(1);
} else if (json[0] == '+') {
json = json.substr(1);
}
if (json.empty() || !isdigit(json[0])) {
throw runtime_error("Parse error: Expected digit");
}
int exponent = 0;
while (!json.empty() && isdigit(json[0])) {
exponent = exponent * 10 + (json[0] - '0');
json = json.substr(1);
}
if (exponent_negative) {
exponent = -exponent;
}
value *= pow(10, exponent);
}
if (negative) {
value = -value;
}
return new JsonNumber(value);
}
};
int main() {
string json = "{\"name\": \"John Smith\", \"age\": 42, \"isMale\": true, \"children\": [{\"name\": \"Alice\", \"age\": 10}, {\"name\": \"Bob\", \"age\": 8}]}";
JsonParser parser(json);
JsonValue *value = parser.parse();
value->print();
delete value;
return 0;
}
```
这个解析器支持JSON中的null、布尔值、数值、字符串、数组和对象等各种类型,可以递归地打印JSON对象。您可以通过修改类的定义来实现自己的行为。
阅读全文