Json是一种轻量级的数据交换格式(也叫数据序列化方式)。Json采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 Json 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
数据序列化格式还有:xml、protobuf,其中protobuf存储数据更为高效,在企业级项目中更常见。——RPC项目用的就是protobuf
本项目中用的Json第三方库是Json for Modern C++,由德国大牛nlohmann编写的在C++下使用的Json库。该库只有一个json.hpp头文件,使用C++11编写,使得使用json就像使用STL容器一样,且STL容器和json之间可以相互转换。
序列化是将数据结构或是对象转换为二进制串(字节序列)的过程,也就是将具有一定结构的对象转换为可以存储或传输的形式。在序列化期间,对象将其当前状态写入到临时或持久性存储区(如硬盘)。这样我们就可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。
反序列化就是上述的逆过程。
比如我们把json格式的对象转换成字符串,再转换成char*,这样就能在网络上传输,或者写进硬盘——由结构化的数据转成地址值
反过来我们把从网络上接收到的字符串对象转成json对象,就是重新构建出json对象结构,这就是反序列化
所以对象序列化的目的:
1、把对象的字节序列永久保存在硬盘上(以某种储存方式使自定义对象持久化);
2、在网络上传送对象的二进制序列(将对象从一个地方传递到另一个地方);
3、使程序更具维护性。
其实就是两个函数:
序列化--------js.dump()//不用传参,json对象js访问成员函数
反序列化-----json::parse(字符串对象)
下列测试代码来自施磊老师课程笔记
#include "json.hpp"
using json = nlohmann::json;
#include<iostream>
using namespace std;
//json序列化演示
void func1(){
json js;
//就像map容器一样,key - value
js["msg_num"] = 2;
js["from"] = "zhang san";
js["to"] = "li si";
js["mas"] = "hello, it's my first cpp program";
cout<< js <<endl;
}
int main(){
func1();
return 0;
}
神奇,可以直接输出json对象js————json肯定对输出运算符做了重载,存数据的时候又能像map容器一样。
输出结果:
{"from":"zhang san","mas":"hello, it's my first cpp program","msg_type":2,"to":"li si"}
可以看到,并不是msg_type第一个插进去就第一个输出/第一个位置存,它是按照key的首字母顺序来存放和输出的,就像有序哈希表map一样
json 转化为 字符串:
json要通过网络发送肯定还是要转成字符串类型,而string在网络上传播是char*形式
string Str = json.dump();//dump函数就可以将json的序列化数据转成string形式,dump本意有转储,导出的意思
//string也封装了将string转换为char*的方法
char* a = Str.c_str();
cout<< a <<endl;
变成字符串其实输出的还是之前那样的结果,相当于在外面加了“”符号
json的键对应的值value除了上面的int ,string类型,还可以是数组类型,甚至是json类型,而且键本身也可以是二维数组类型,如下:
void func2(){
json js;
js["id"] = {1, 2, 3, 4, 5};
js["name"] = "zhang san";
//添加对象,key可以是二维数组
js["msg"]["liu shuo"] = "hello A";
js["msg"]["zhang san"] = "hello B";//js[键1][键2]
//下面等同于上面两行,两种形式输出都一样
js["msg"] = {{"liu shuo", "hello A"}, {"zhang san", "hello B"}};//用两个json对象给js的msg赋值
cout<<js<<endl;
}
输出:
{"id":[1,2,3,4,5],"msg":{"liu shuo":"hello A","zhang san":"hello B"},"name":"zhang san"}
可以看到msg对应的值是一个json,两个json赋值给msg后变成了一个json,而且,js["msg"]["liu shuo"]的意义就是先访问js的键msg,再访问msg中的键liu shuo,还有就是,liu和zhang的顺序也被改了,因为两者在msg这个json里面就是键,是有顺序的
json甚至能将容器序列化,其实就是value还可以是容器类型
void func3(){
json js;
//序列化vector容器
vector<int> vec;
vec.push_back(1);
vec.push_back(2);
vec.push_back(5);
js["list"] = vec;
//序列化map容器
map<int, string> m;
m.insert({1, "黄山"});
m.insert({2, "华山"});
m.insert({3, "泰山"});
js["path"] = m;
cout<<js<<endl;
}
输出:
{"list":[1,2,5],"path":[[1,"黄山"],[2,"华山"],[3,"泰山"]]}
map这个键值对容器转成json后,变成二维数组了
假设我们收到字符串形式的json,我们把它转成json格式,用json::parse()函数,parse是语法分析,解析。
其实就是,对方服务器有json数据,转成字符串,这样方便发给我们,我们再把它重塑为json
下面测试123是对应上面测试123的反序列化
string func1(){
json js;
//就像map容器一样,key - value
js["msg_type"] = 2;
js["from"] = "zhang san";
js["to"] = "li si";
js["msg"] = "hello, it's my first cpp program";
string Str = js.dump();
return Str;
}
int main(){
string s = func1();
json js = json::parse(s);
cout<<js["msg_type"]<<endl;
cout<<js["from"]<<endl;
cout<<js["msg"]<<endl;
return 0;
}
输出:
2
"zhang san"
"hello, it's my first cpp program"
string func2(){
json js;
js["id"] = {1, 2, 3, 4, 5};
js["name"] = "zhang san";
js["msg"]["liu shuo"] = "hello A";
js["msg"]["zhang san"] = "hello B";
return js.dump();
}
int main(){
json js = json::parse(func2());
cout<<js["id"]<<endl;
cout<<js["msg"]<<endl;
cout<<js["msg"]["zhang san"]<<endl;
return 0;
}
输出:
[1,2,3,4,5]
{"liu shuo":"hello A","zhang san":"hello B"}
"hello B"
下面测试3更能体现反序列化的意义!
string func3(){
json js;
//序列化vector容器
vector<int> vec;
vec.push_back(1);
vec.push_back(2);
vec.push_back(5);
js["list"] = vec;
//序列化map容器
map<int, string> m;
m.insert({1, "黄山"});
m.insert({2, "华山"});
m.insert({3, "泰山"});
js["path"] = m;
return js.dump();
}
int main(){
json js = json::parse(func3());
vector<int> nums = js["list"];//因为js里面的list的值是vector形式数据
map<int, string>mp = js["path"];
for(auto& a : nums){
cout<<a<<endl;
}
for(int i = 0; i < mp.size(); ++i){
cout<<mp[i]<<endl;
}
return 0;
}
结果:
1
2
5
//这里输出了一个空字符串,map[0]对应的value(string类型)
黄山
华山
泰山
上述代码中,用下标去给map做输出,而map的[]里应该是key,所以i = 0时,因为map没有对应元素,所以被新增到容器中,此时容器大小变为4,所以能访问下标[3],map[0]其对应的初始值为空字符串
所以用迭代器访问map更好,这样不会新增元素,而且不会越界。
for(auto& p : mp){
cout<<p.first<<" "<<p.second<<endl;
}
加上上述代码后输出如下:

在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这
给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最
我有一个非常简单的RubyRack服务器,例如:app=Proc.newdo|env|req=Rack::Request.new(env).paramspreq.inspect[200,{'Content-Type'=>'text/plain'},['Somebody']]endRack::Handler::Thin.run(app,:Port=>4001,:threaded=>true)每当我使用JSON对象向服务器发送POSTHTTP请求时:{"session":{"accountId":String,"callId":String,"from":Object,"headers":
?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------
我正在使用ruby2.1.0我有一个json文件。例如:test.json{"item":[{"apple":1},{"banana":2}]}用YAML.load加载这个文件安全吗?YAML.load(File.read('test.json'))我正在尝试加载一个json或yaml格式的文件。 最佳答案 YAML可以加载JSONYAML.load('{"something":"test","other":4}')=>{"something"=>"test","other"=>4}JSON将无法加载YAML。JSON.load("
假设我必须(小型到中型)阵列:tokens=["aaa","ccc","xxx","bbb","ccc","yyy","zzz"]template=["aaa","bbb","ccc"]如何确定tokens是否以相同的顺序包含template的所有条目?(请注意,在上面的示例中,应忽略第一个“ccc”,从而由于最后一个“ccc”而导致匹配。) 最佳答案 这适用于您的示例数据。tokens=["aaa","ccc","xxx","bbb","ccc","yyy","zzz"]template=["aaa","bbb","ccc"]po
首先,我使用的是rails3.1.3和来自master的carrierwavegithub仓库的分支。我使用after_init钩子(Hook)来确定基于属性的字段页面模型实例并为这些字段定义属性访问器将值存储在序列化哈希中(希望它清楚我是什么谈论)。这是我正在做的事情的精简版:classPage省略mount_uploader命令让我可以访问我想要的属性。但是当我安装uploader时出现错误消息说“nil类的未定义新方法”我在源代码中读到有方法read_uploader和扩展模块中的write_uploader。我如何必须覆盖这些来制作mount_uploader命令使用我的“虚拟
我在一个简单的RailsAPI中有以下Controller代码:classApi::V1::AccountsControllerehead:not_foundendendend问题在于,生成的json具有以下格式:{id:2,name:'Simpleaccount',cash_flows:[{id:1,amount:34.3,description:'simpledescription'},{id:2,amount:1.12,description:'otherdescription'}]}我需要我生成的json是camelCase('cashFlows'而不是'cash_flows'
我正在学习如何使用JSONgem解析和生成JSON。我可以轻松地创建数据哈希并将其生成为JSON;但是,在获取一个类的实例(例如Person实例)并将其所有实例变量放入哈希中以转换为JSON时,我脑袋放屁。这是我遇到问题的例子:require"json"classPersondefinitialize(name,age,address)@name=name@age=age@address=addressenddefto_jsonendendp=Person.new('JohnDoe',46,"123ElmStreet")p.to_json我想创建一个.to_json方法,这样我就可以获
我正在构建一个带有Rails后端的JS应用程序,为了不混淆snake和camelcases,我想通过从服务器返回camelcase键名来规范化这一切。因此,当从API返回时,user.last_name将返回user.lastName。我如何实现这一点?谢谢!编辑:添加Controller代码classApi::V1::UsersController 最佳答案 我的方法是使用ActiveModelSerializer和json_api适配器:在你的Gemfile中,添加:gem'active_model_serializers'创建