include: co/json.h.
co.json is a JSON library similar to rapidjson. Compared with rapidjson, it has better performance and is easier to use.
#Basic concepts
JSON is a simple data format that supports two data structures:
- A collection consisting of a series of key/value pairs. This type of structure is called object, which corresponds to struct, map, etc, in programming languages.
- A list composed of a series of value, this kind of structure is called array, which corresponds to vector, list, etc, in programming languages.
In the above, the key is a string, and the value is generally called JSON value, which can be any of object, array, number, string, bool(false, true), or null. number is an integer or a floating-point number, and most implementations will distinguish integers from floating-point numbers.
Object is enclosed by a pair of braces, array is enclosed by a pair of square brackets, they look like this:
{"a":1, "b":false, "s":"xxx"}
[1, 2, 3]
By definition, object and array can be nested, which can represent complex data structures such as trees.
#global
#json::array
Json array();
- This function is in namespace json, it returns an empty array.
#json::object
Json object();
- This function is in namespace json, it returns an empty object.
#json::parse
Json parse(const char* s, size_t n);
Json parse(const char* s);
Json parse(const fastring& s);
Json parse(const std::string& s);
- Parse Json from a JSON string.
- This function is not a method in the Json class, but a function defined in
namespace json. - This function returns a Json object, when the parsing failed, it returns null.
#co::Json
#constructor
1. Json() noexcept;
2. Json(decltype(nullptr)) noexcept;
3. Json(Json&& v) noexcept;
4. Json(Json& v) noexcept;
Json(const Json& v) = delete;
5. Json(bool v);
6. Json(double v);
7. Json(int64 v);
8. Json(int32 v);
9. Json(uint32 v);
10. Json(uint64 v);
11. Json(const void* p, size_t n);
12. Json(const char* s);
13. Json(const fastring& s);
14. Json(const std::string& s);
15. Json(std::initializer_list<Json> v);
-
1-2, construct a null object.
-
3-4, move constructor and copy constructor, both implement a move semantic, the parameter
vwill become a null object after the construction. -
5, construct a JSON object of bool type.
-
6, construct a JSON object of double type.
-
7-10, construct a JSON object of integer type.
-
11-14, construct a JSON object of string type.
-
15, construct a JSON object of object or array type from a initialization list.
-
Example
co::Json a; // null
co::Json b(nullptr); // null
co::Json c = false; // bool
co::Json d = 3.14; // double
co::Json e = 23; // integer
co::Json f = "xx"; // string
co::Json g = {1, 2, 3}; // g -> [1, 2, 3]
co::Json h = {"a", "b"}; // h -> ["a", "b"]
co::Json i = { // i -> { "a": "b" }
{"a", "b"}
};
co::Json j = { // j -> {"a": 1, "b": [1,2,3]}
{"a", 1},
{"b", {1, 2, 3}},
};
co::Json x(i); // i -> null
co::Json y(std::move(j)); // j -> null
#operator=
Json& operator=(Json&& v);
Json& operator=(Json& v);
void operator=(const Json&) = delete;
- Assignment, the 2 methods above are equal,
vis moved to the calling Json object, and becomes a null object after the operation.
#dup
Json dup() const;
-
Return a deep copy of a JSON object.
-
η€ΊδΎ
co::Json x = {1, 2, 3}; // x -> [1,2,3]
co::Json y, z;
y = x; // x -> null, y -> [1,2,3]
z = y.dup(); // y:[1,2,3], z -> [1,2,3]
#βββββββββββ
#is_null
bool is_null() const;
- Determine whether the Json is null.
#is_bool
bool is_bool() const;
- Determine whether the Json is bool type.
#is_int
bool is_int() const;
- Determine whether the Json is integer type.
#is_double
bool is_double() const;
- Determine whether the Json is double type.
#is_string
bool is_string() const;
- Determine whether the Json is string type.
#is_array
bool is_array() const;
- Determine whether the Json is array type.
#is_object
bool is_object() const;
- Determine whether the Json is object type.
#βββββββββββ
#as_bool
bool as_bool() const;
- Get value of bool type.
- For int or double types, returns false if the value is 0, otherwise returns true.
- For string type, returns true if the value is
"true"or"1", otherwise returns false. - For other non-bool types, return false.
#as_int
int as_int() const;
int32 as_int32() const;
int64 as_int64() const;
- Get value of integer type.
- For bool, double or string types, the result is automatically converted to an integer.
- For other non-integer types, 0 is returned.
#as_double
double as_double() const;
- Get value of double type. Return 0 if the Json object calling this method is not double type.
- Get value of double type.
- For bool, int or string types, the result is automatically converted to double type.
- For other non-double types, 0 is returned.
#as_string
fastring as_string() const;
- Get value of string type, return fastring.
- For non-string types, this method is equal to str(), and the result will be automatically converted to string type.
#as_c_str
const char* as_c_str() const;
- Returns a null-terminated C-style string, string_size() can be called to get its length.
- For non-string types, return an empty string.
#get
1. Json& get(uint32 i) const;
2. Json& get(int i) const;
3. Json& get(const char* key) const;
4. template <class T, class ...X>
inline Json& get(T&& v, X&& ... x) const;
- Get JSON object according to index or key. This method is a read-only operation and will not modify the JSON object that calls this method.
- 1-2, get the i-th element of the array object. If the JSON object that calls this method is not of type array, or
iexceeds the range of the array, the returned result will refer to a null object. - 3, get the JSON value corresponding to
key, if the JSON object called this method is not of type object, orkeydoes not exist, the returned result will refer to a null object. - 4, can take any number of parameters, each parameter is an index or a key. When it encounters the first invalid index or non-existing key, it returns immediately, and the return result will refer to a null object.
#set
template <class T>
inline Json& set(T&& v) {
return *this = Json(std::forward<T>(v));
}
template <class A, class B, class ...X>
inline Json& set(A&& a, B&& b, X&& ... x);
- Set the value of the JSON object.
- The last parameter of
setis the value to be set, other parameters are index or key.
#Example
co::Json r = {
{ "a", 7 },
{ "b", false },
{ "c", { 1, 2, 3 } },
{ "s", "23" },
};
r.get("a").as_int(); // 7
r.get("b").as_bool(); // false
r.get("s").as_string(); // "23"
r.get("s").as_int(); // 23
r.get("c", 0).as_int(); // 1
r.get("c", 1).as_int(); // 2
// x -> {"a":1,"b":[0,1,2],"c":{"d":["oo"]}}
co::Json x;
x.set("a", 1);
x.set("b", co::Json({0,1,2}));
x.set("c", "d", 0, "oo");
#βββββββββββ
#operator==
bool operator==(bool v) const;
bool operator==(double v) const;
bool operator==(int64 v) const;
bool operator==(int v) const;
bool operator==(uint32 v) const;
bool operator==(uint64 v) const;
bool operator==(const char* v) const;
bool operator==(const fastring& v) const;
bool operator==(const std::string& v) const;
- Check if the value of the Json object is equal to
v. - If the type of the Json object is different from
v, return false directly.
#operator!=
bool operator!=(bool v) const;
bool operator!=(double v) const;
bool operator!=(int64 v) const;
bool operator!=(int v) const;
bool operator!=(uint32 v) const;
bool operator!=(uint64 v) const;
bool operator!=(const char* v) const;
bool operator!=(const fastring& v) const;
bool operator!=(const std::string& v) const;
- Check if the value of the Json object is not equal to
v. - If the type of the Json object is different from
v, return true directly.
#Example
co::Json x = {
{"a", 3},
{"b", false},
{"s", "xx"},
};
x == 7; // false
x["a"] == 3; // true
x["b"] == false; // true
x["s"] == "xx"; // true
#βββββββββββ
#add_member
Json& add_member(const char* key, Json&& v);
Json& add_member(const char* key, Json& v);
-
Add a key-value pair to a Json of object type (non-object Json automatically becomes object after calling this method).
-
This method will reserve the order in which keys were added, and keys may appear repeatedly.
-
The parameter key is a C string ending in
'\0', and the parameter v is the value. -
vis moved and becomes null after this operation. -
NOTE: for performance reasons, it is required that the key cannot contain double quotes.
-
Example
co::Json r;
r.add_member("a", 1); // r -> {"a":1}
r.add_member("d", 3.3); // r -> {"a":1, "d":3.3}
r.add_member("s", "xx"); // r -> {"a":1, "d":3.3, "s":"xx"}
co::Json x;
x.add_member("xx", r); // r -> null
r.add_member("o", co::Json().add_member("x", 3)); // r -> {"o":{"x":3}}
co::Json().add_member("o", 1).add_member("k", 2); // -> {"o":1,"k":2}
#erase
void erase(uint32 i);
void erase(int i);
void erase(const char* key);
- The first two, erase the ith element from an array.
- The third, erase the element by
keyfrom an object.
#push_back
Json& push_back(Json&& v);
Json& push_back(Json& v);
-
Add elements to an array (non-array Json automatically becomes an array after calling this method).
-
vis moved and becomes null after this operation. -
Example
co::Json r;
r.push_back(1); // r -> [1]
r.push_back(3.3); // r -> [1, 3.3]
r.push_back("xx"); // r -> [1, 3.3, "xx"]
co::Json x;
x.push_back(r); // r -> null, x -> [[1, 3.3, "xx"]]
r.push_back(co::Json().push_back(1).push_back(2)); // r -> [[1,2]]
#remove
void remove(uint32 i);
void remove(int i);
void remove(const char* key);
- The first two, remove the ith element from an array.
- The third, remove the element by
keyfrom an object. - The last element will be moved to the position where the element was removed.
#reset
void reset();
- Reset the Json object to null.
#swap
void swap(Json& v) noexcept;
void swap(Json&& v) noexcept;
- Swap the contents of two Json objects.
#βββββββββββ
#operator[]
Json& operator[](uint32 i) const;
Json& operator[](int i) const;
Json& operator[](const char* key) const;
-
Overload
operator[], get the elements in the Json by index or key. -
1-2, for array type, get the i-th element of the array object, i must be within the size range of the array.
-
3, for object type, when the key does not exist, a null object will be inserted into the Json.
-
In general, it is recommended to replace this operation with the read-only
get()method whenever possible. -
Example
co::Json r = {
{ "a", 7 },
{ "x", { 1, 2, 3 } },
};
r["a"].as_int(); // 7
r["x"][0].as_int(); // 1
#has_member
bool has_member(const char* key) const;
-
Determine whether there is an element corresponding to key in Json.
-
Return false if the Json calling this method is not object type.
-
Example
co::Json r = {{"a", 1}};
r.has_member("a"); // true
r.has_member("x"); // false
#size
uint32 size() const;
-
If Json is object or array, this method returns the number of elements.
-
If Json is string type, this method returns the length of the string.
-
For all other types, this method returns 0.
-
Example
co::Json r = {
{"x", 1},
{"s", "hello"},
{"a", {1, 2, 3}},
};
r.size(); // 3
r["x"].size(); // 0
r["s"].size(); // 5
r["a"].size(); // 3
#empty
bool empty() const;
- Check whether the Json is empty, which is equal to
size() == 0.
#string_size
uint32 string_size() const;
- Return the length of the string type. Return 0 if the Json calling this method is not string type.
#array_size
uint32 array_size() const;
- Return the number of elements of array type. Return 0 if the Json calling this method is not array type.
#object_size
uint32 object_size() const;
- Return the number of elements of object type. Return 0 if the Json calling this method is not object type.
#βββββββββββ
#str
fastream& str(fastream& s, int mdp=16) const;
fastring& str(fastring& s, int mdp=16) const;
fastring str(int mdp=16) const;
- Convert Json to a string.
- The 1st version appends the JSON string to a fastream, and the return value is the same as the parameter s.
- The 2nd version appends the JSON string to a fastring, and the return value is the same as the parameter s.
- The 3rd version returns a JSON string.
- The parameter
mdpis short formax decimal places, which means the maximum number of decimal places for float point numbers.
#pretty
fastream& pretty(fastream& s, int mdp=16) const;
fastring& pretty(fastring& s, int mdp=16) const;
fastring pretty(int mdp=16) const;
- Like the str(), but convert Json to a more beautiful JSON string.
#dbg
fastream& dbg(fastream& s, int mdp=16) const;
fastring& dbg(fastring& s, int mdp=16) const;
fastring dbg(int mdp=16) const;
- Convert Json to a debug string, like
str(), but will truncate string type to the first 32 bytes if its length exceeds 512 bytes. - This method is generally used to print logs. In some cases, the Json object may contain a long string, such as the base64 encoding of a picture. At such cases, use
dbg()instead ofstr()to avoid printing too many significant logs.
#parse_from
bool parse_from(const char* s, size_t n);
bool parse_from(const char* s);
bool parse_from(const fastring& s);
bool parse_from(const std::string& s);
- Parse Json from a JSON string.
- In the first version, s is not required to end with
'\0'. - When the parsing is successful, it returns true, otherwise it returns false.
- When the parsing fails, the calling Json becomes null.
#Example
co::Json r = {
{ "a", {1,2,3} }
};
fastring s = r.str(); // s -> {"a":[1,2,3]}
fastring p = r.pretty();
LOG << r.dbg(); // print json debug string
LOG << r; // the same as above, but is more efficient
co::Json x;
x.parse_from(s);
x.parse_from(p);
co::Json v = json::parse(s);
#βββββββββββ
#begin
iterator begin() const;
- Returns the beginning iterator.
- The Json calling this method must be array, object or null.
- When the Json is empty, the return value is equal to
end(). - If the Json calling this method is not array or object type, the return value is equal to end().
#end
const iterator::End& end() const;
- Returns a fake end iterator.
- The return value is actually not an iterator object, but a iterator can be compared with it. If an iterator is equal to
end(), it means that there is no more element.
#iterator
#operator==
bool operator==(const End&) const;
- Determine whether a iterator is equal to
End, End is the fake end iterator.
#operator!=
bool operator!=(const End&) const;
- Determine if a iterator is not equal to
End, End is the fake end iterator.
#operator++
iterator& operator++();
- The prefix operator++.
#operator*
Json& operator*() const;
- Overload
operator*, this method only applies to iterator of array type. - When Json is an array, the iterator points to the elements in the array.
#key
const char* key() const;
- This method only applies to iterator of object type.
- When Json is an object, the iterator points to the key-value pair in the object, and this method returns the key.
#value
Json& value() const;
- This method only applies to iterator of object type.
- When Json is an object, the iterator points to the key-value pair in the object, and this method returns the value.
#Traversing the Json
co.json supports traversing a Json of type array or object by iterator:
// {"i":7, "s":"xx", "a":[123, true, "nice"]}
co::Json r = {
{"i", 7},
{"s", "xx"},
{"a", {1, 2, 3}},
}
// object
for (auto it = r.begin(); it != r.end(); ++it) {
LOG << it.key() << ": " << it.value();
}
// array
co::Json& a = r["a"];
for (auto it = a.begin(); it != a.end(); ++it) {
LOG << (*it);
}
#Performance tips
Some users may add members in the following way:
co::Json r;
r["a"] = 1;
r["s"] = "hello world";
Although the above code works, the efficiency may be not so good. The operator[] will first look up the key, which may be slow. It is generally recommended to use add_member() instead:
co::Json r;
r.add_member("a", 1);
r.add_member("s", "hello world");
Or construct a Json like this:
co::Json r = {
{"a", 1},
{"s", "hello world"},
};
For read-only operations, it is recommended to replace operator[] with get(), which has no side effects.
co::Json r = {{"a", 1}};
r.get("a").as_int(); // 1