This is the second part of open source code learning. The previous one is: "Solve json parsing and encapsulation problems in one article, and take you to learn CJSON open source code"
This article reads the code of json11. Json11 is a JSON library written in C++11. Children interested in json11 code or use can read this article.
json11
json11 is a lightweight C++11 library that provides JSON serialization and deserialization functions,
When parsing json data, I tried several json libraries and finally decided to use json 11 for the following reasons:
- Common functions of json
- It can be used just like using C + + classes
- Chinese is not garbled, which is the main reason why I chose this library
github address of json11: json11.
json11 source code reading
Project structure
The project structure is relatively simple, with only two files
json11.hpp
json11.cpp
ReamME
JSON 11 is a lightweight C++11 library, which provides JSON serialization and deserialization functions
The core object is json11::Json. It can be used to represent any type of JSON data:
null, bool, number (int or double), string (std::string), array (std::vector), or object (std::map)
json11::Json objects, like other value types, support assignment, copy, transfer, comparison and other operations. We also provide auxiliary methods
Json::dump is used to serialize json11::Json type objects into string Json::parse
(static) used to deserialize std::string to an object of type json11::Json
Using the initializer provided by C++11, you can easily create a json11::Json object:
Json my_json = Json::object { { "key1", "value1" }, { "key2", false }, { "key3", Json::array { 1, 2, 3 } }, }; std::string json_str = my_json.dump();
Some built-in constructors are also provided here, which can automatically convert standard library types and user-defined types into json11::Json objects. For example:
class Point { public: int x; int y; Point (int x, int y) : x(x), y(y) {} Json to_json() const { return Json::array { x, y }; } }; std::vector<Point> points = { { 1, 2 }, { 10, 20 }, { 100, 200 } }; std::string points_json = Json(points).dump(); json11::
Json supports both subscript and keyword indexes:
Json json = Json::array { Json::object { { "k", "v" } } }; std::string str = json[0]["k"].string_value();
json11 design
It is mainly composed of the following categories
- class Json
- class JsonValue
- class Value
- class JsonInt JsonDouble ...
The Json class is an open interface with various construction methods.
class Json final { public // Types enum Type { NUL, NUMBER, BOOL, STRING, ARRAY, OBJECT }; typedef std::vector<Json> array; //array and object are directly implemented using STL container typedef std::map<std::string, Json> object; Json() noexcept; // NUL Json(std::nullptr_t) noexcept; // NUL Json(double value); // NUMBER Json(int value); // NUMBER Json(bool value); // BOOL Json(const std::string &value); // STRING Json(std::string &&value); // STRING Json(const char * value); // STRING Json(const array &values); // ARRAY Json(array &&values); // ARRAY Json(const object &values); // OBJECT Json(object &&values); // OBJECT template <class T, class = decltype(&T::to_json)> Json(const T & t) : Json(t.to_json()) {} template <class M, typename std::enable_if< std::is_constructible<std::string, decltype(std::declval<M>().begin()->first)>::value && std::is_constructible<Json, decltype(std::declval<M>().begin()->second)>::value, int>::type = 0> Json(const M & m) : Json(object(m.begin(), m.end())) {} template <class V, typename std::enable_if< std::is_constructible<Json, decltype(*std::declval<V>().begin())>::value, int>::type = 0> Json(const V & v) : Json(array(v.begin(), v.end())) {} Json(void *) = delete; ... private: std::shared_ptr<JsonValue> m_ptr;
Several constructors are complex. See the following for details:
The entities of these data are stored in M_ The object pointed to by PTR.
class JsonValue { protected: friend class Json; friend class JsonInt; friend class JsonDouble; virtual Json::Type type() const = 0; virtual bool equals(const JsonValue * other) const = 0; virtual bool less(const JsonValue * other) const = 0; virtual void dump(std::string &out) const = 0; virtual double number_value() const; virtual int int_value() const; virtual bool bool_value() const; virtual const std::string &string_value() const; virtual const Json::array &array_items() const; virtual const Json &operator[](size_t i) const; virtual const Json::object &object_items() const; virtual const Json &operator[](const std::string &key) const; virtual ~JsonValue() {} };
JsonValue is an abstract base class that defines APIs for manipulating and accessing JSON objects. These APIs are not open to users for internal use. Users operate and access by the functions provided in the JSON class.
Next is its derived class Value:
template <Json::Type tag, typename T> class Value : public JsonValue { protected: // Constructors explicit Value(const T &value) : m_value(value) {} explicit Value(T &&value) : m_value(move(value)) {} // Get type tag Json::Type type() const override { return tag; } // Comparisons bool equals(const JsonValue * other) const override { return m_value == static_cast<const Value<tag, T> *>(other)->m_value; } bool less(const JsonValue * other) const override { return m_value < static_cast<const Value<tag, T> *>(other)->m_value; } const T m_value; void dump(string &out) const override { json11::dump(m_value, out); } };
As a class template, Value instantiates different classes that hold the data entities of json objects.
JsonInt, JsonDouble and other classes can directly inherit the corresponding instantiated classes to save data.
Take JsonInt as an example:
class JsonInt final : public Value<Json::NUMBER, int> { double number_value() const override { return m_value; } int int_value() const override { return m_value; } bool equals(const JsonValue * other) const override { return m_value == other->number_value(); } bool less(const JsonValue * other) const override { return m_value < other->number_value(); } public: explicit JsonInt(int value) : Value(value) {} };
The inherited value is an int version, so you can save value directly through the parent constructor. It also implements some operations specific to this class, such as int_value() is used to get the value of value.
reference material
https://www.cnblogs.com/cknightx/p/7717539.html