不落辰

知不可乎骤得,托遗响于悲风

0%

JSON简介

json for morden c++

简介

  • Json(JavaScript Object Notation)是一种轻量级的数据交换格式(也叫数据序列化方式)。JSON 使用 JavaScript 语法来描述数据对象,但是 JSON 仍然独立于语言和平台。简洁和清晰的层次结构使得 Json 成为理想的数据交换语言。易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
  • 道格拉斯·克罗克福特(Douglas Crockford)设计的JSON实际上是JavaScript的一个子集,故此,在Json中的数据类型有这几种。
    • number:和JavaScript的number完全一致;
    • boolean:就是JavaScript的true或false;
    • string:就是JavaScript的string;
    • null:就是JavaScript的null;
    • array:就是JavaScript的Array表示方式——[];
    • object:就是JavaScript的{ … }表示方式。
    • 以及上面的任意组合。
  • 并且,JSON规定字符集必须是UTF-8,表示多语言就没有问题了。为了统一解析,JSON的字符串规定必须用双引号””,Object的键也必须用双引号””。
  • 几乎所有编程语言都有解析JSON的库。而在JavaScript中,在语言层面内置了对象的JSON序列化和反序列化的API。
  • 感觉json对象就是一个key-value表,其中key-value都用string””表示,可能会存在一个key对应多个{key-value}的情况

好用的cpp库:JSON for Modern C++

  • JSON for Modern C++ 是一个由德国大牛 nlohmann 编写的在 C++ 下使用的 JSON 库。具有以下特点
    • 直观的语法
    • 整个代码由一个头文件组成 json.hpp,没有子项目,没有依赖关系,没有复杂的构建系统,使用起来非常方便
    • 使用 C++ 11 标准编写
    • 使用 json 像使用 STL 容器一样
    • STL 和 json 容器之间可以相互转换
    • 严谨的测试:所有类都经过严格的单元测试,覆盖了 100% 的代码,包括所有特殊的行为。此外,还检查了 Valgrind 是否有内存泄漏。
    • 为了保持高质量,该项目遵循核心基础设施倡议(CII)的最佳实践

使用

1
2
3
4
5
6
7
8
9
10
11
#include "json.hpp"
using json = nlohmann::json;

// 定义json对象
json js;
// 输出json对象
cout<<json<<endl;
// json -> string
string send_buf = js.dump();
// string -> json
json js = json::parse(send_buf);

Json序列化

  • 就是把我们想要打包的数据,或者对象,直接处理成Json字符串
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    #include"json.hpp"
    #include<iostream>
    #include<string>
    #include<vector>
    #include<unordered_map>

    using json = nlohmann::json;
    using std::cout;
    using std::endl;
    using std::string;
    using std::vector;
    using std::unordered_map;

    // 序列化示例1 普通数据序列化
    void func1()
    {
    json js;
    js["msg_type"] = 2;
    js["from"] = "zhang san";
    js["to"] = "li si";
    js["msg"] = "hello,what are you doing?";

    cout<<js<<endl;

    string send_buf = js.dump();
    cout<<send_buf<<endl;

    // {"from":"zhang san","msg":"hello,what are you doing?","msg_type":2,"to":"li si"}
    // {"from":"zhang san","msg":"hello,what are you doing?","msg_type":2,"to":"li si"}
    }



    // 序列化示例2 普通数据序列化
    void func2()
    {
    json js;
    // 添加数组
    js["id"] = {1,2,3,4,5};
    // 添加key-value
    js["name"] = "张三";
    // 添加对象 (即一个msg数组里面有多个key-value)
    js["msg"]["zhang san"] = "hello";
    js["msg"]["liu shuo"] = "bye";
    // 上面等同于这句一次性添加数组对象
    js["msg"] = {{"zhang san","hello2"},{"li si","bye2"}};

    cout<<js<<endl;
    // {"id":[1,2,3,4,5],"msg":{"li si":"bye2","zhang san":"hello2"},"name":"张三"}

    }


    // 序列化示例2 容器序列化
    void func3()
    {
    json js;
    vector<int> vec;
    vec.push_back(1);
    vec.push_back(2);
    vec.push_back(3);
    js["list"] = vec;

    unordered_map<int,string> m;
    m.insert({1,"a"});
    m.insert({2,"b"});
    m.insert({3,"c"});

    js["map"] = m;

    cout<<js<<endl;

    // {"list":[1,2,3],"map":[[3,"c"],[1,"a"],[2,"b"]]}
    }

Json反序列化

  • 当从网络接收到字符串为Json格式,可以用JSON for Modern C++ 直接反序列化取得数据或者直接反序列化出对象,甚至容器!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
//  反序列化取key
string func1()
{
json js;
js["msg_type"] = 2;
js["from"] = "zhang san";
js["to"] = "li si";
js["msg"] = "hello,what are you doing?";

return js.dump(); // return string send_buf
}

string receive_buf = func1();
json js_buf = json::parse(receive_buf);
cout<<js_buf["msg_type"]<<endl;
cout<<js_buf["from"]<<endl;
cout<<js_buf["to"]<<endl;
cout<<js_buf["msg"]<<endl;
// 2
// "zhang san"
// "li si"
// "hello,what are you doing?"



====================================

// 直接反序列化vector容器
string func2()
{
json js;
// 添加数组
js["id"] = {1,2,3,4,5};
// 添加key-value
js["name"] = "张三";
// 添加对象 (即一个msg数组里面有多个key-value)
js["msg"]["zhang san"] = "hello";
js["msg"]["li si"] = "bye";
// 上面等同于这句一次性添加数组对象
// key"msg" 对应的value类型 还是一个{{}{}}json
js["msg"] = {{"zhang san","hello2"},{"li si","bye2"}};

return js.dump();
}

string receive_buf = func2();
json js_buf = json::parse(receive_buf);

cout<<js_buf["id"]<<endl; // [1,2,3,4,5]
vector<int> vec = js_buf["id"]; // 1 2 3 4 5
for(int x:vec){
cout<<x<<" ";
}
cout<<endl;

cout<<js_buf["name"]<<endl;
// json中的json类型应用json来接收
json js_msg = js_buf["msg"];
cout<<js_msg["zhang san"]<<endl;
cout<<js_msg["li si"]<<endl;

[1,2,3,4,5]
1 2 3 4 5
"张三"
"hello2"
"bye2"

=============================================

// 直接反序列化map容器
string func3()
{
json js;
vector<int> vec;
vec.push_back(1);
vec.push_back(2);
vec.push_back(3);
js["list"] = vec;

unordered_map<int,string> m;
m.insert({1,"a"});
m.insert({2,"b"});
m.insert({3,"c"});

js["map"] = m;

return js.dump();
}

// json中的数组类型可以用容器vector接收 ; unordered_map可用unordered_map / json来接收
string receive_buf = func3();
json js_buf = json::parse(receive_buf);
vector<int> v = js_buf["list"];
for(int i=0;i<v.size();++i){
cout<<v[i]<<" ";
}
cout<<endl;

unordered_map<int,string> m = js_buf["map"];
cout<<m[1]<<endl;


json jsm = js_buf["map"];
cout<<jsm<<endl;
return 0;

shc@shc-virtual-machine:~/json_learn/build$ ../bin/json_test
1 2 3
a
[[3,"c"],[1,"a"],[2,"b"]]

json里的数据类型都是本身的数据类型套一个 “ string “ “ int “
要取出本身的类型:js[“xxx”].get js[“xxxx”].get
但好像不取也没影响?