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/。
本篇文章分析到這里,歡迎點贊,分享,收藏,關注。