diff --git a/json_parser.cpp b/json_parser.cpp new file mode 100644 index 0000000..c560d86 --- /dev/null +++ b/json_parser.cpp @@ -0,0 +1,278 @@ +#include +#include +#include +#include + +class JsonValue { +public: + typedef enum ValueType { + Integer, + Float, + String, + Boolean, + Object, + Array, + } ValueType; +public: + JsonValue() = default; + + virtual ~JsonValue() = default; + + virtual ValueType type() = 0; +}; + +template +class PrimeValue : public JsonValue { +public: + PrimeValue(const T &data) : data_(data) {} + + ValueType type() override { + if (std::is_same_v) { + return ValueType::Integer; + } else if (std::is_same_v) { + return ValueType::Boolean; + } else if (std::is_same_v || std::is_same_v) { + return ValueType::Float; + } else if (std::is_same_v) { + 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 &value) { + data_.push_back(value); + } + +private: + std::deque> 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 &value) { + data_ = value; + } + + template + void setValue(const T &value) { + data_ = std::make_shared>(value); + } + + const std::string &getName() const { return name_; } + + template + const T &getValue() { + return (dynamic_pointer_cast>(data_))->get(); + } + +private: + std::string name_; + std::shared_ptr 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 &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 + 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(); + } + return T{}; + } + +private: + std::deque> data_; +}; + +std::shared_ptr Parse(const std::string &json_string) { + int pair_index{-1}; + int colon_index{-1}; + std::vector memory; + std::shared_ptr root_node{nullptr}; + std::vector> parents; + std::shared_ptr parent_node{nullptr}; + std::shared_ptr 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 parent_object = dynamic_pointer_cast(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(str); + } else if (colon_index < 0 && parent_node->type() == JsonValue::ValueType::Array) { + std::shared_ptr parent_array = dynamic_pointer_cast(parent_node); + parent_array->AddValue(std::make_shared>(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 parent_object = dynamic_pointer_cast( + parent_node); + parent_object->AddValue(next_value); + next_value.reset(); + } else { + std::shared_ptr parent_array = dynamic_pointer_cast( + parent_node); + parent_array->AddValue(std::make_shared>(double_value)); + } + } else { + auto int_value = std::stoi(tmp); + if (next_value) { + next_value->setValue(int_value); + std::shared_ptr parent_object = dynamic_pointer_cast( + parent_node); + parent_object->AddValue(next_value); + next_value.reset(); + } else { + std::shared_ptr parent_array = dynamic_pointer_cast( + parent_node); + parent_array->AddValue(std::make_shared>(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 parent_object = dynamic_pointer_cast(parent_node); + parent_object->AddValue(next_value); + next_value.reset(); + } else { + std::shared_ptr parent_array = dynamic_pointer_cast(parent_node); + parent_array->AddValue(std::make_shared>(bool_value)); + } + } + } + colon_index = -1; + break; + } + case '{': + parents.push_back(std::make_shared()); + 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()); + 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(json_obj); + std::cout << "name: " << obj_value->getValue("name") << '\n'; + std::cout << "age: " << obj_value->getValue("age") << '\n'; + std::cout << "is_student: " << obj_value->getValue("is_student") << '\n'; + } + + return 0; +}