#include "archiver.h" #include #include ////////////////////////////////////////////////////////////////////////////// // Test1: simple object struct Student { Student() : name(), age(), height(), canSwim() {} Student(const std::string name, unsigned age, double height, bool canSwim) : name(name), age(age), height(height), canSwim(canSwim) {} std::string name; unsigned age; double height; bool canSwim; }; template Archiver& operator&(Archiver& ar, Student& s) { ar.StartObject(); ar.Member("name") & s.name; ar.Member("age") & s.age; ar.Member("height") & s.height; ar.Member("canSwim") & s.canSwim; return ar.EndObject(); } std::ostream& operator<<(std::ostream& os, const Student& s) { return os << s.name << " " << s.age << " " << s.height << " " << s.canSwim; } void test1() { std::string json; // Serialize { Student s("Lua", 9, 150.5, true); JsonWriter writer; writer & s; json = writer.GetString(); std::cout << json << std::endl; } // Deserialize { Student s; JsonReader reader(json.c_str()); reader & s; std::cout << s << std::endl; } } ////////////////////////////////////////////////////////////////////////////// // Test2: std::vector <=> JSON array // // You can map a JSON array to other data structures as well struct Group { Group() : groupName(), students() {} std::string groupName; std::vector students; }; template Archiver& operator&(Archiver& ar, Group& g) { ar.StartObject(); ar.Member("groupName"); ar & g.groupName; ar.Member("students"); size_t studentCount = g.students.size(); ar.StartArray(&studentCount); if (ar.IsReader) g.students.resize(studentCount); for (size_t i = 0; i < studentCount; i++) ar & g.students[i]; ar.EndArray(); return ar.EndObject(); } std::ostream& operator<<(std::ostream& os, const Group& g) { os << g.groupName << std::endl; for (std::vector::const_iterator itr = g.students.begin(); itr != g.students.end(); ++itr) os << *itr << std::endl; return os; } void test2() { std::string json; // Serialize { Group g; g.groupName = "Rainbow"; Student s1("Lua", 9, 150.5, true); Student s2("Mio", 7, 120.0, false); g.students.push_back(s1); g.students.push_back(s2); JsonWriter writer; writer & g; json = writer.GetString(); std::cout << json << std::endl; } // Deserialize { Group g; JsonReader reader(json.c_str()); reader & g; std::cout << g << std::endl; } } ////////////////////////////////////////////////////////////////////////////// // Test3: polymorphism & friend // // Note that friendship is not necessary but make things simpler. class Shape { public: virtual ~Shape() {} virtual const char* GetType() const = 0; virtual void Print(std::ostream& os) const = 0; protected: Shape() : x_(), y_() {} Shape(double x, double y) : x_(x), y_(y) {} template friend Archiver& operator&(Archiver& ar, Shape& s); double x_, y_; }; template Archiver& operator&(Archiver& ar, Shape& s) { ar.Member("x") & s.x_; ar.Member("y") & s.y_; return ar; } class Circle : public Shape { public: Circle() : radius_() {} Circle(double x, double y, double radius) : Shape(x, y), radius_(radius) {} ~Circle() {} const char* GetType() const { return "Circle"; } void Print(std::ostream& os) const { os << "Circle (" << x_ << ", " << y_ << ")" << " radius = " << radius_; } private: template friend Archiver& operator&(Archiver& ar, Circle& c); double radius_; }; template Archiver& operator&(Archiver& ar, Circle& c) { ar & static_cast(c); ar.Member("radius") & c.radius_; return ar; } class Box : public Shape { public: Box() : width_(), height_() {} Box(double x, double y, double width, double height) : Shape(x, y), width_(width), height_(height) {} ~Box() {} const char* GetType() const { return "Box"; } void Print(std::ostream& os) const { os << "Box (" << x_ << ", " << y_ << ")" << " width = " << width_ << " height = " << height_; } private: template friend Archiver& operator&(Archiver& ar, Box& b); double width_, height_; }; template Archiver& operator&(Archiver& ar, Box& b) { ar & static_cast(b); ar.Member("width") & b.width_; ar.Member("height") & b.height_; return ar; } class Canvas { public: Canvas() : shapes_() {} ~Canvas() { Clear(); } void Clear() { for (std::vector::iterator itr = shapes_.begin(); itr != shapes_.end(); ++itr) delete *itr; } void AddShape(Shape* shape) { shapes_.push_back(shape); } void Print(std::ostream& os) { for (std::vector::iterator itr = shapes_.begin(); itr != shapes_.end(); ++itr) { (*itr)->Print(os); std::cout << std::endl; } } private: template friend Archiver& operator&(Archiver& ar, Canvas& c); std::vector shapes_; }; template Archiver& operator&(Archiver& ar, Shape*& shape) { std::string type = ar.IsReader ? "" : shape->GetType(); ar.StartObject(); ar.Member("type") & type; if (type == "Circle") { if (ar.IsReader) shape = new Circle; ar & static_cast(*shape); } else if (type == "Box") { if (ar.IsReader) shape = new Box; ar & static_cast(*shape); } return ar.EndObject(); } template Archiver& operator&(Archiver& ar, Canvas& c) { size_t shapeCount = c.shapes_.size(); ar.StartArray(&shapeCount); if (ar.IsReader) { c.Clear(); c.shapes_.resize(shapeCount); } for (size_t i = 0; i < shapeCount; i++) ar & c.shapes_[i]; return ar.EndArray(); } void test3() { std::string json; // Serialize { Canvas c; c.AddShape(new Circle(1.0, 2.0, 3.0)); c.AddShape(new Box(4.0, 5.0, 6.0, 7.0)); JsonWriter writer; writer & c; json = writer.GetString(); std::cout << json << std::endl; } // Deserialize { Canvas c; JsonReader reader(json.c_str()); reader & c; c.Print(std::cout); } } ////////////////////////////////////////////////////////////////////////////// int main() { test1(); test2(); test3(); }