#头文件
#include "co/json.h"
API 在 json 命名空间。
#json::any
json::any 表示任意 JSON 值,类型可以是 null、bool、int、double、string、array 或 object。
#构造与拷贝
any(); // null
any(decltype(nullptr)); // null
any(any&& v); // 移动
any(any& v); // 移动(非 const)
any(const any&) = delete;
void operator=(const any&) = delete;
any& operator=(any&& v); // 移动
any& operator=(any& v); // 移动
any dup() const; // 显式深拷贝
any(bool v);
any(double v);
any(int64 v);
any(int32 v);
any(uint32 v);
any(uint64 v);
any(const void* p, size_t n); // 初始化字符串类型
any(const char* s);
any(const co::string& s);
any(const std::string& s);
any(std::initializer_list<any> v);
- 禁用拷贝构造、拷贝赋值。
- 支持移动,移动后源对象变成 null。
dup()递归深拷贝。- 整数统一存
int64。
示例:
json::any a; // null
json::any b(nullptr); // null
json::any c(false); // bool
json::any d(3.14); // double
json::any e(23); // integer
json::any f("xx"); // string
json::any g = {1, 2, 3}; // [1, 2, 3]
json::any h = {"a", "b"}; // ["a", "b"]
json::any i = { // { "a": "b" }
{"a", "b"}
};
json::any j = { // {"a": 1, "b": [1,2,3]}
{"a", 1},
{"b", {1, 2, 3}},
};
json::any x(h); // h -> null
json::any y(std::move(i)); // i -> null
y = j; // j -> null
#类型查询与取值
int type() const;
bool is_null() const;
bool is_bool() const;
bool is_int() const;
bool is_double() const;
bool is_string() const;
bool is_array() const;
bool is_object() const;
bool as_bool() const;
int64 as_int64() const;
int32 as_int32() const;
int as_int() const;
double as_double() const;
const char* as_c_str() const;
co::string as_string() const;
若 JSON 不是相应类型,as_xxx() 会尝试类型转换:
as_bool():非 0 为 true,字符串"true"或"1"为 true,其余 false。as_int64():字符串用 co::stoi64。as_double():字符串用 co::stod。as_c_str():非 string 返回""。as_string():null 返回"",非 string 返回str()。
#访问与修改
any& get() const;
any& get(uint32 i) const;
any& get(int i) const;
any& get(const char* key) const;
template<typename T, typename ...X>
any& get(T&& v, X&& ... x) const;
template<typename T>
any& set(T&& v);
template<typename A, typename B, typename ...X>
any& set(A&& a, B&& b, X&& ... x);
any& operator[](uint32 i) noexcept;
any& operator[](int i) noexcept;
const any& operator[](uint32 i) const noexcept;
const any& operator[](int i) const noexcept;
any& operator[](const char* key) noexcept;
const any& operator[](const char* key) const noexcept;
get只读,越界或 key 不存在返回内部 null 对象的引用。set不存在时创建,最后一个参数是值,其余参数是索引或 key。operator[]:- const 版本只读,等价于
get(i)/get(key); - 非 const 版本不存在时创建,若当前类型不匹配,会先重置为 array 或 object。
- const 版本只读,等价于
示例:
json::any 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"]}}
json::any x;
x.set("a", 1);
x.set("b", json::any({0,1,2}));
x.set("c", "d", 0, "oo");
#添加与删除
any& add_member(const char* key, any&& v);
any& add_member(const char* key, any& v);
any& push_back(any&& v);
any& push_back(any& v);
void remove(uint32 i); // 末尾移到 i,O(1),打乱顺序
void remove(int i);
void remove(const char* key);
void erase(uint32 i); // 前移,O(n),保持顺序
void erase(int i);
void erase(const char* key);
add_member添加 key-value 到 object 中(非 object 先重置为 object),允许重复 key。push_back添加元素到 array 末尾(非 array 先重置为 array)。- 参数
v采用 move 语义;调用后v变为 null。 remove、erase删除 array 或 object 中元素。remove是O(1),可能打乱元素顺序;erase是O(n),移动元素保持顺序。
示例:
json::any r;
r.add_member("i", 1); // r -> {"i":1}
r.add_member("d", 3.3); // r -> {"i":1, "d":3.3}
r.add_member("s", "xx"); // r -> {"i":1, "d":3.3, "s":"xx"}
json::any x;
x.add_member("xx", r); // r -> null
r.add_member("o", json::any().add_member("x", 3)); // r -> {"o":{"x":3}}
json::any c;
c.push_back(1).push_back(2); // c -> [1,2]
json::any d;
d.push_back(c); // c -> null, d -> [[1, 2]]
#序列化
co::string str(int mdp=16) const; // 紧凑
co::string dbg(int mdp=16) const; // 截断长字符串(>512 字节)
co::string pretty(int mdp=16) const; // 缩进 4 空格
mdp:浮点数最大有效小数位数,默认 16。
示例:
#include "co/json.h"
#include "co/print.h"
int main() {
json::any x;
x.add_member("name", "coost");
x.add_member("version", 4);
co::println("str: ", x.str());
co::println("pretty:\n", x.pretty());
return 0;
}
#大小
uint32 size() const;
bool empty() const;
uint32 array_size() const;
uint32 object_size() const;
uint32 string_size() const;
size():array 元素数,object 键值对数,string 长度,其它 0。empty()等价于size() == 0。array_size()/object_size()/string_size()仅对应类型返回长度,其它 0。
#has_member
bool has_member(const char* key) const;
- 判断
key是否存在,非 object 类型返回 false。
#iterator
struct iterator {
bool operator!=(_End) const;
bool operator==(_End) const;
iterator& operator++();
const char* key() const;
any& value() const;
any& operator*() const;
};
iterator begin() const;
const iterator::_End end() const;
- array:
operator*返回元素。 - object:
key()返回键,value()返回值。 - 不支持后缀
++。
object 类型的 iterator,不允许使用 operator*。
示例:
#include "co/json.h"
#include "co/print.h"
int main() {
// 用 iterator 遍历 object
json::any x;
x.add_member("a", 1);
x.add_member("b", 2);
for (auto it = x.begin(); it != x.end(); ++it) {
co::println(it.key(), " = ", it.value().as_int());
}
// 用 iterator 遍历 array
json::any y;
y.push_back(1).push_back(2);
for (auto it = y.bengin(); it != y.end(); ++it) {
co::println(*it);
}
// 用索引遍历 array
for (uint32 i = 0; i < y.array_size(); ++i) {
co::println(y[i]);
}
return 0;
}
#解析
json::any json::parse(const char* s, size_t n);
json::any json::parse(const char* s);
json::any json::parse(const co::string& s);
json::any json::parse(const std::string& s);
- 将字符串解析成 JSON 对象,失败返回 null。
示例:
#include "co/json.h"
#include "co/print.h"
int main() {
const char* s = R"({"name":"coost","version":4,"tags":["cpp","coroutine"]})";
json::any x = json::parse(s);
co::println("name: ", x["name"].as_c_str());
co::println("version: ", x["version"].as_int());
auto& tags = x.get("tags");
for (uint32 i = 0; i < tags.array_size(); ++i) {
co::println("tag[", i, "] = ", tags[i].as_c_str());
}
return 0;
}
#快速创建 array 或 object
json::any json::array(); // 返回空 array
json::any json::object(); // 返回空 object
json::any json::array(std::initializer_list<any> v);
json::any json::object(std::initializer_list<any> v);
示例:
json::any a = json::array({1,2,3});
json::any o = json::object({
{"a", 1},
{"s", "hello world"},
});
#终端或日志中打印 JSON
coost 重载了如下操作符,可在 co::print 或日志中直接打印 json::any。
co::string& operator<<(co::string& s, const json::any& x) noexcept;
示例:
json::any o = json::object({
{"a", 1},
{"s", "hello world"},
});
co::println("o: ", o);
log::info("o: ", o);
#性能优化建议
有些用户喜欢用如下方式添加元素:
json::any r;
r["a"] = 1;
r["s"] = "hello world";
可行,但效率不高。operator[] 先查找 key,找到就更新值,没找到插入新元素。建议用 add_member() 方法取代:
json::any r;
r.add_member("a", 1);
r.add_member("s", "hello world");
或者像下面这样构造:
json::any r = {
{"a", 1},
{"s", "hello world"},
};