1.Json语法
JSON 语法是 JAVAScript 语法的子集。一个 json 对象包含了字符串、整数、浮点数、普通数组、对象、对象数组等。
{
"name": "qaa",
"age": 80,
"professional": {
"english": 4,
"putonghua": 2,
"computer": 3,
},
"languages": ["C++", "C"],
"phone": {
"number": "123456789",
"type": "home"
},
"books": [{
"name": "linux kernel development",
"price": 7.7
}, {
"name": "Linux server development",
"price": 8.0
}],
"vip": true,
"address": null
}
上面代码中,数组的表示"languages":["C++", "C"],数组用大括号表示。
数组里面也可以放对象进去。对象用{ }表示。
"books":[{
"name": "Linux kernel development",
"price": 7.7
},
{
"name": "Linux server development",
"price": 8.0
}
]
JSON 语法规则
JSON 语法是 JavaScript 对象表示语法的子集。
(1)数据在名称/值对中
(2)数据由逗号分隔
(3)大括号保存对象
(3)中括号保存数组
JSON 名称/值对
JSON 数据的书写格式是:名称/值对。名称在双引号,名称后面写一个冒号。
"name":"qaa"。
Json值类型:
(1)数字(整数或浮点数),如{ "age":30 }
(2)字符串(在双引号)
(3)bool值(true或false)
(4)数组(在中括号中),数组可包含多个对象。"sites" 是包含三个对象的数组。每个对象代表一条关于某个网站(name、url)的记录。
{
"sites":[
{"name":"json与xml学习","url":"www.toutiao.com"},
{"name":"google","url":"www.google.com"},
{"name":"头条","url":"www.toutiao.com"}
]
}
(5)对象(在大括号),如{"name":"json与xml学习","url":"www.toutiao.com"}
(6)Json可以设置为null值。{"address":null}
2.Jsoncpp安装
jsoncpp 是一个 c++封装的 json 包,跨平台支持 windows、linux、unix 等多系统。
jsoncpp 源码地址:https://github.com/open-source-parsers/jsonc
安装
apt-get install libjsoncpp-dev
库的头文件安装在/usr/include/jsoncpp 中,库 API 文档默认在/usr/share/doc/libjsoncpp-dev/jsoncpp-api-html/目录下。
#include <jsoncpp/json/json.h>
#include <IOStream>
#include <string>
#include "jsoncpp/json/json.h"
#include "jsoncpp/json/value.h"
#include "jsoncpp/json/writer.h"
using namespace std;
int main()
{
cout << "Hello World!" << endl;
Json::Value root;
Json::FastWriter fast;
root["ModuleType"] = Json::Value(1);
root["ModuleCode"] = Json::Value("China");
cout<<fast.write(root)<<endl;
Json::Value sub;
sub["version"] = Json::Value("1.0");
sub["city"] = Json::Value(root);
fast.write(sub);
cout<<sub.toStyledString()<<endl;
return 0;
}
编译
g++ jsoncpp_test.c -o test -ljsoncpp
Jsoncpp 支持的值
jsoncpp 使用 Json::Value 对象来保存 JSON 串,Json::Value 对象可以表示如下数据类型:
检测保存的数据类型
bool isNull() const;
bool isBool() const;
bool isInt() const;
bool isInt64() const;
bool isUInt() const;
bool isUInt64() const;
bool isIntegral() const;
bool isDouble() const;
bool isNumeric() const;
bool isString() const;
bool isArray() const;
bool isObject() const;
基础数据类型的访问
const char* asCString() const;
JSONCPP_STRING asString() const;
Int asInt() const;
UInt asUInt() const;
Int64 asInt64() const;
UInt64 asUInt64() const;
LargestInt asLargestInt() const;
LargestUInt asLargestUInt() const;
float asFloat() const;
double asDouble() const;
bool asBool() const;
ValueType::arrayValue 和 ValueType::objectValue 数据类型的访问,操作方式很类似C++的 vector,可以使用数组风格或者迭代器风格来操作数据。
ArrayIndex size() const;
Value& operator[](ArrayIndex index);
Value& operator[](int index);
const Value& operator[](ArrayIndex index) const;
const Value& operator[](int index) const;
Value get(ArrayIndex index, const Value& defaultValue) const;
const_iterator begin() const;
const_iterator end() const;
iterator begin();
iterator end();
ValueType::objectValue 数据类型的访问,操作方式很类似 C++的 map
Value& operator[](const char* key);
const Value& operator[](const char* key) const;
Value& operator[](const JSONCPP_STRING& key);
const Value& operator[](const JSONCPP_STRING& key) const;
Value& operator[](const StaticString& key);
Value& operator[](const CppTL::ConstString& key);
const Value& operator[](const CppTL::ConstString& key) const;
Value get(const char* key, const Value& defaultValue) const;
Value get(const char* begin, const char* end, const Value& defaultValue) const;
Value get(const JSONCPP_STRING& key, const Value& defaultValue) const;
Value get(const CppTL::ConstString& key, const Value& defaultValue) const;
修改数据
如何修改 Json::Value 保存的数据:
Value(ValueType type = nullValue);
Value(Int value);
Value(UInt value);
Value(Int64 value);
Value(UInt64 value);
Value(double value);
Value(const char* value);
Value(const char* begin, const char* end);
Value(const StaticString& value);
Value(const JSONCPP_STRING& value);
Value(const CppTL::ConstString& value);
Value(bool value);
Value(const Value& other);
Value(Value&& other);
注意:对于Int、Uint、Int64、UInt64 等类型,注意类型。root["age"] = 80;默认为int类型,如root["age"] = (Json::Uint)80;强制转换类型。
若要将变量设置为Null,则使用root["address"] = Json::nullValue;
3.CJson编译安装
下载
git clone https://github.com/DaveGamble/cJSON.git
参考 Readme 进行编译
直接使用 cJSON.h 和 cJSON.c 加入到源文件。
cJSON 结构
next、prev用于遍历数组或对象链的前后向链表指针;child指向数组或对象的孩子节点,type是value的类型,valuestring 是字符串值,valueint是整数值,valuedouble是浮点数值,string是key的名字。
cJSON 支持的类型
valuestring,当类型为cJSON_String或cJSON_Raw时,value的值,type不符合是为NULL
valueint,当类型为cJSON_Number 时,value的值。
valuedouble,当类型为cJSON_NUmber 时,value 的值
string,代表 key,value 键值对中 key 的值
cJSON_Parse
函数:
功能:按照cJson结构体序列化整个数据包,并在堆中开辟一块内存存储cJSON结构体。
返回值:成功返回一个指向内存块中的cJSON的指针,失败返回NULL。
cJSON_Delete
功能:释放位于堆中cJSON结构体内存。
注意:使用cJSON_Parse()获取cJSON指针后,若不再使用,则需调用cJSON_Delete()对其释放,否则会导致内存泄漏。
cJSON_Print
功能:
把cJSON数据解析成JSON字符串,并在堆中开辟一块char*的内存空间存储JSON字符串。cJSON_PrintUnformatted()与 cJSON_Print()类似,只打印输出不带格式,只是一个字符串数据。
返回值:
返回一个char*指针指向位于堆中JSON字符串,失败返回NULL。
注意:可以把cJSON链表中所有的cJSON对象打印出来,但是需要手动释放资源。free(char *)。
cJSON_Version
功能:获取当前使用的 cJSON 库的版本号。
返回值:返回一个字符串数据。
cJSON_GetArrayItem
功能:
从object 的cJSON链表中寻找key为string的CJSON对象
返回值:
成功返回一个指向cJSON类型的结构体指针,失败返回NULL。
与 cJSON_GetObjectItem()类似的接口还有:
函数简介
4.XML简介
XML 是 Extensible Markup Language 的缩写,即可扩展标记语言。使用 XML 标记语言可以做到数据或数据结构在任何编程语言环境下的共享。
XML 和 HTML 的区别
(1)在 HTML 中不区分大小写,在 XML 中对大小写要求非常严格。
(2)HTML 使用固有的标记,而 XML 没有固有标记。
(3)HTML 用于显示页面,把数据和显示结合在一起,在页面中展示这些数据。而XML把页面内容的数据或结构与显示分开。
XML 的优点
1.搜索,XML中可以提取文档的中任何位置的数据。
2.显示,将数据的结构和数据的显示形式分开,根据需要使数据呈现出多种显示方式,如HTML、PDF 等格式。
3.数据交换,XML标记语法简单,能通过解析器在任何机器上解读。能够在各种计算机平台上使用,逐渐成为一种数据交换的语言。
XML 使用场景
XML 大多用于本地化场景。在网络传输中,解析速度比不上json,protobuf等协议。
文件配置
Android 的应用配置文件
Java 中的 pom.xml 应用 配置文件
Tomcat 中的 server.xml 应用 配置文件
如Android 和 QT 都使用 XML 来配置界面
QT 界面配置文件
Android 界面配置文件
游戏中的关卡,英雄等级,装备之类,显示框大小,颜色之类
XML 文档的组成
XML 文档也属于纯文本文件,该文档一般如下四部分组成:
(1)XML文档声明
(2)XML文档类型定义
(3)XML文档注释
(4)XML标识及其内容(主体)
前面3步都是可选:
<?xml version="1.0" encoding="UTF-8"?>
<!--XML 文档注释-->
<?xml:stylesheet type="text/xsl"href="stu.xsl"?>
<!--班级中学生的信息-->
<class>
<student>
<name>Jone</name>
<age>20</age>
</student>
</class>
XML 的语法规则
(1)结束标记不能忽略,在XML文档中必须有起始标记。
(2)区分大小写。开始标记和结束标记的大小写必须相同。
(3)正确嵌套包含
<b><i>This text is bold and italic</i></b>
正确嵌套的意思是:由于 <i> 元素是在 <b> 元素内打开的,那么它必须在 <b> 元素内关闭。
XML 文档的元素一般是由标记头、标记末和标记间的字符串数据构成,如下图所示:
XML 文档中的第一个元素被称为根元素,有且只有一个元素,其它元素就成为子元素,子元素必须正确嵌套在根元素中。若元素的值存在空格,那就必须将这些空格的原样解析出来。
在 XML 中,省略关闭标签是非法的。所有元素都必须有关闭标签:
<p>This is a paragraph</p>
<p>This is another paragraph</p>
(4)在 XML 中,XML 的属性值须加引号。请研究下面的两个 XML 文档。第一个是错误的,第二个是正确的:
在第一个文档中的错误是,note 元素中的 date 属性没有加引号。
实体
预定义实体表如下所示:
实体在XML文档的一般引用格式如下:
&实体名;
属性
属性是用来修饰某个元素,如:
<root>
<a attribute="aa"> this is test</a>
</root>
注意:
(1)属性值必须引用引号括起来,如: attribute1=“aa” 或 attribute3=‘aa' ;
(2)元素的属性以名和值成对出现
(3)修饰同一个元素的属性的属性名不能相同
(4)属性值不能包含“&”、“’”、“<”等字符。
如果你把字符 "<" 放在 XML 元素中,会发生错误,这是因为解析器会把它当作新元素的开始。
会产生 XML 错误:
<message>if salary < 1000 then</message>
避免这个错误,请用一个实体引用来代替 "<" 字符,引用主要是针对一些特殊字符。
<message>if salary < 1000 then</message>
(5)XML 中编写注释的语法与 HTML 的语法很相似:
<!-- This is a comment -->
XML 树结构
XML文档是一种树结构,它从“根部”开始,然后扩展到“枝叶”。
<?xml version="1.0" encoding="utf-8"?>
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
解释:
第一行是XML声明。它定义XML版本和所使用的编码(utf-8)。
下一行描述文档的根元素<note>接下来4行描述根的4个子元素(to,from,heading,body)。
最后一行定义根元素的结尾:</note>
XML 命名规则
(1)名称可以包含字母,数字以及其它字符
(2)名称不能以数字或标点符号开始
(3)不能以字符"xml"(或XML、Xml)开始
(4)名称不能包含空格
(5)可使用任何名称,没有保留的字符
(6)名称具有描述性
(7)名称应当比较简短,如<book_title>,而不是:<the_title_of_the_book>。
(8)避免 "-" 字符,否则会认为需要提取第一个单词。
(9)避免 "." 字符,否则会认为"name"是对象"first"的属性。
(10) 避免 ":" 字符,冒号会被认为命名空间来使用。
(11)XML 文档经常有一个对应的数据库,一般使用数据库的名称规则来命名XML文档的元素。
XML 属性
(1)XML元素可在开始标签中包含属性,类似HTML
(2)属性(Attribute)提供关于元素的额外信息
属性通常提供不属于数据组成部分的信息。文件类型与数据无关。
<file type="gif">computer.gif</file>
元素与属性
第一个表示sex是一个属性,第二个例子,sex是一个元素。两个 例子均可提供相同信息。
因使用属性而引起的一些问题:
(1)属性无法包含多个值(子元素可以)
(2)属性无法描述树结构(子元素可以)
尽量使用元素来描述数据。仅仅适用属性来提供与数据无关的信息,比如类似QT那样用属性标识类别及对象名。
(3)向元素分配ID引用。用于标识XML元素,起作用的方式与HTML中属性ID是一样。如下面这种情况。
这个id只是一个标识符,用于标识不同标签,并不是标签数据的组成部分。
5.TinyXml2 库使用
TinyXML2 安装
(1) 下载 tinyxml2
git clone https://github.com/leethomason/tinyxml2.git
(2)进入目录并编译
cd tinyxml2/
cmake .
make
(3)测试版本的准确性
./xmltest
如果是fail 0就说明正常。
(4)安装
make install
可以看到安装的路径
可以直接在工程引入 tinyxml2.h 和 tinyxml2.cpp 即可。
Tinyxml2 简介
TinyXML2 是简单实用的开源的 C++XML 文件解析库,可以很方便的应用到现有的项目之中。TinyXML2 解析器相对 TinyXML1 在代码上是完全重写,使其更适合于游戏开发中使用。它使用更少的内存,更快,并使用更少的内存分配。
由于 XML 的树状结构,TinyXML2 将 XML 的节点抽象为 XMLNode,XML 中除了把属性 key-value 抽象为 XMLAttribute 类型外,其余的都看作 XMLNode 的子类,首先将整个XML 文档抽象为 XMLDocument,将声明部分抽象为 XMLDeclaration,将注释抽象为XMLComment,将元素抽象为 XMLElement,将文本抽象为 XMLText。
节点、 元素、 属性、 值的关系
注意:元素一定是节点,节点不一定是元素。
API 用法
从本地文件读取 xml
tinyxml2::XMLDocument doc;
doc.LoadFile( "test.xml" );
std::cout << doc.ErrorID() << std::endl;
从内存中加载 xml
static const char* xml = "<element/>";
tinyxml2::XMLDocument doc;
doc.Parse( xml );
std::cout << doc.ErrorID() << std::endl;
6.XML检测工具
使用在线工具去检查XML在线代码格式化。检查是否正确。
XML 在线代码格式化 http://tool.oschina.net/codeformat/xml/。
本篇文章分析到这里,欢迎点赞,分享,收藏,关注。