upload a semi-finished json parser.
This commit is contained in:
parent
29f18d4f1f
commit
505a8128a8
|
@ -0,0 +1,278 @@
|
|||
#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;
|
||||
}
|
Loading…
Reference in New Issue