JsonParser/json_parser.cpp

279 lines
9.8 KiB
C++
Raw Normal View History

2024-03-22 20:49:51 +08:00
#include <iostream>
#include <deque>
#include <memory>
#include <stack>
class JsonValue {
public:
typedef enum ValueType {
Integer,
Float,
String,
Boolean,
Object,
Array,
} ValueType;
public:
JsonValue() = default;
virtual ~JsonValue() = default;
virtual ValueType type() = 0;
};
template<typename T>
class PrimeValue : public JsonValue {
public:
PrimeValue(const T &data) : data_(data) {}
ValueType type() override {
if (std::is_same_v<T, int>) {
return ValueType::Integer;
} else if (std::is_same_v<T, bool>) {
return ValueType::Boolean;
} else if (std::is_same_v<T, float> || std::is_same_v<T, double>) {
return ValueType::Float;
} else if (std::is_same_v<T, std::string>) {
return ValueType::String;
} else {
static_assert("PrimeValue type instance failed!");
}
}
public:
void set(const T &value) { data_ = value; }
const T &get() const { return data_; }
private:
T data_;
};
class ArrayValue : public JsonValue {
public:
ArrayValue() = default;
ValueType type() override { return ValueType::Array; }
void AddValue(const std::shared_ptr<JsonValue> &value) {
data_.push_back(value);
}
private:
std::deque<std::shared_ptr<JsonValue>> data_;
};
class NamedValue {
public:
NamedValue() = default;
explicit NamedValue(const std::string &name) : name_(name) { std::cout << name << '\n'; }
public:
void setValue(const std::shared_ptr<JsonValue> &value) {
data_ = value;
}
template<typename T>
void setValue(const T &value) {
data_ = std::make_shared<PrimeValue<T>>(value);
}
const std::string &getName() const { return name_; }
template<typename T>
const T &getValue() {
return (dynamic_pointer_cast<PrimeValue<T>>(data_))->get();
}
private:
std::string name_;
std::shared_ptr<JsonValue> data_;
};
class ObjectValue : public JsonValue {
public:
ObjectValue() = default;
explicit ObjectValue(const std::string &str) {}
ValueType type() override { return ValueType::Object; }
void AddValue(const std::shared_ptr<NamedValue> &value) {
data_.push_back(value);
}
bool Contains(const std::string &key) {
return data_.end() !=
std::find_if(data_.begin(), data_.end(), [&key](const auto &item) {
return key == item->getName();
});
}
template<typename T>
T getValue(const std::string &key) const {
auto it = std::find_if(data_.begin(), data_.end(), [&key](const auto &item) {
return key == item->getName();
});
if (data_.end() != it) {
return (*it)->template getValue<T>();
}
return T{};
}
private:
std::deque<std::shared_ptr<NamedValue>> data_;
};
std::shared_ptr<JsonValue> Parse(const std::string &json_string) {
int pair_index{-1};
int colon_index{-1};
std::vector<char> memory;
std::shared_ptr<JsonValue> root_node{nullptr};
std::vector<std::shared_ptr<JsonValue>> parents;
std::shared_ptr<JsonValue> parent_node{nullptr};
std::shared_ptr<NamedValue> next_value{nullptr};
for (int i = 0; i < json_string.size(); ++i) {
char c = json_string[i];
switch (c) {
case '"':
if (pair_index >= 0 && pair_index < memory.size()) {
std::string str{};
std::cout << "i: " << i << ", pair_index: " << pair_index << ", memory.size(): " << memory.size()
<< '\n';
for (int j = pair_index + 1; j < memory.size(); ++j) {
str += memory[j];
}
printf("%s, size: %d\n", str.c_str(), str.size());
memory.erase(memory.begin() + pair_index, memory.end());
if (colon_index >= 0 && next_value) {
next_value->setValue(str);
std::shared_ptr<ObjectValue> parent_object = dynamic_pointer_cast<ObjectValue>(parent_node);
parent_object->AddValue(next_value);
next_value = nullptr;
} else {
if (colon_index < 0 && parent_node->type() == JsonValue::ValueType::Object) {
next_value = std::make_shared<NamedValue>(str);
} else if (colon_index < 0 && parent_node->type() == JsonValue::ValueType::Array) {
std::shared_ptr<ArrayValue> parent_array = dynamic_pointer_cast<ArrayValue>(parent_node);
parent_array->AddValue(std::make_shared<PrimeValue<std::string>>(str));
}
}
pair_index = -1;
} else {
pair_index = memory.size();
memory.push_back(c);
}
break;
case ',': {
bool point_existed{false};
bool all_digit{true};
std::string tmp;
for (int j = 0; j < memory.size(); ++j) {
tmp += memory[j];
if (memory[j] == '.') {
point_existed = true;
} else if (all_digit && !std::isdigit(memory[j])) {
all_digit = false;
}
}
memory.clear();
printf("%s\n", tmp.c_str());
if (!tmp.empty()) {
if (all_digit) {
if (point_existed) {
auto double_value = std::stod(tmp);
if (next_value) {
next_value->setValue(double_value);
std::shared_ptr<ObjectValue> parent_object = dynamic_pointer_cast<ObjectValue>(
parent_node);
parent_object->AddValue(next_value);
next_value.reset();
} else {
std::shared_ptr<ArrayValue> parent_array = dynamic_pointer_cast<ArrayValue>(
parent_node);
parent_array->AddValue(std::make_shared<PrimeValue<double>>(double_value));
}
} else {
auto int_value = std::stoi(tmp);
if (next_value) {
next_value->setValue(int_value);
std::shared_ptr<ObjectValue> parent_object = dynamic_pointer_cast<ObjectValue>(
parent_node);
parent_object->AddValue(next_value);
next_value.reset();
} else {
std::shared_ptr<ArrayValue> parent_array = dynamic_pointer_cast<ArrayValue>(
parent_node);
parent_array->AddValue(std::make_shared<PrimeValue<int>>(int_value));
}
}
} else {
bool bool_value;
if (tmp == "true") {
bool_value = true;
} else if (tmp == "false") {
bool_value = false;
} else {
static_assert("Parse value error!");
}
if (next_value) {
next_value->setValue(bool_value);
std::shared_ptr<ObjectValue> parent_object = dynamic_pointer_cast<ObjectValue>(parent_node);
parent_object->AddValue(next_value);
next_value.reset();
} else {
std::shared_ptr<ArrayValue> parent_array = dynamic_pointer_cast<ArrayValue>(parent_node);
parent_array->AddValue(std::make_shared<PrimeValue<bool>>(bool_value));
}
}
}
colon_index = -1;
break;
}
case '{':
parents.push_back(std::make_shared<ObjectValue>());
parent_node = parents.back();
if (parents.size() == 1) {
root_node = parents[0];
}
break;
case '}':
parents.pop_back();
parent_node = parents.back();
break;
case '[':
parents.push_back(std::make_shared<ArrayValue>());
parent_node = parents.back();
if (parents.size() == 1) {
root_node = parents[0];
}
case ']':
parents.pop_back();
parent_node = parents.back();
break;
case ':':
colon_index = i;
break;
default:
memory.push_back(c);
break;
}
}
return root_node;
}
int main() {
auto json_obj = Parse(R"({"name":"tianlei","age":27,"is_student":true,"assets":["book","phone","computer",],})");
std::cout << json_obj->type() << '\n';
if (json_obj->type() == JsonValue::Object) {
auto obj_value = std::dynamic_pointer_cast<ObjectValue>(json_obj);
std::cout << "name: " << obj_value->getValue<std::string>("name") << '\n';
std::cout << "age: " << obj_value->getValue<int>("age") << '\n';
std::cout << "is_student: " << obj_value->getValue<bool>("is_student") << '\n';
}
return 0;
}