JsonCpp
| 華夏公益教科書人認為此頁面應該拆分成更小的頁面,主題更窄。 您可以透過將此大頁面拆分成更小的頁面來幫助我們。請務必遵循命名規則。將書籍分成更小的部分可以提供更多的關注點,並允許每個部分都能很好地完成一項任務,這對每個人都有好處。 |
本書介紹了 JsonCpp 庫(也稱為 jsoncpp 和 json-cpp),JsonCpp 可能是 C++ 中使用最廣泛的 JSON 資料庫庫。它可以解析和儲存資料庫,並提供一個廣泛的庫來訪問和操作其成員。JsonCpp 可以與檔案和字串一起使用。
對於一個存在多年的庫來說,JsonCpp 的文件化程度令人驚訝地差。您要麼能找到一個非常簡單的使用示例,要麼能找到一個計算機生成的包含所有類和方法的列表。
我既不是該庫的作者,也不是該庫的貢獻者。
JSON(JavaScript 物件表示法)是一種用於表示各種資料結構的 ASCII 格式。它非常獨立於語言、機器、簡單且易於人機閱讀。
JSON 在json.org上進行了全面描述。
簡而言之,JSON 值可以是以下之一(有關完整詳細資訊,請參閱json.org):
- null
- true 或 false
- 數字。
- 數字不能以 0(或 -0)開頭,後跟另一個數字(例如,0 和 0.14 是有效的數字,而 03、012.34 和 -015 不是)。
- 如果數字包含小數點,則它也應該至少包含小數點前後的一個數字(例如,數字 15. 和 .15 是無效的)。
- 字串。字串用雙引號括起來,可以包含以下轉義序列
\" - quote \\ - backslash \/ - slash \n - newline \t - tabulation \r - carriage return \b - backspace \f - form feed \uxxxx , where x is a hexadecimal digit - any 2-byte symbol
- 陣列。它用方括號中以逗號分隔的任何值列表表示。示例
[1, 2, 3, "Hello world\n", true]
- 物件,也稱為關聯陣列、鍵值列表等。它用花括號中以逗號分隔的鍵值對列表表示。鍵值對的格式為
key : value
其中 key 是一個字串,value 是任何 JSON 值。示例
{"foo":1, "bar":2, "baz":3.14, "hello world":[1,2,3]}
可以在任何標記之間插入空格。
陣列元素透過其數字訪問,而物件元素透過鍵訪問。陣列和物件可以為空。陣列和物件可以遞迴地包含其他陣列或物件。
雖然嚴格的 JSON 語法不允許任何註釋,並且要求根值為陣列或物件,但 JsonCpp 允許 C 樣式和 C++ 樣式的註釋,並允許根值為任何型別。
截至 2016 年 2 月,共有數百種庫用於解析和生成 62 種語言的 JSON,包括 22 種不同的 C++ 庫。[1]
JsonCpp 可能是最流行的 C++ 庫。另一個流行的庫是rapidjson,它非常快。
從 Ubuntu 或 Debian Linux 的另一個版本使用它的最簡單方法是,將其安裝為
sudo apt-get install libjsoncpp-dev
(您可以使用 apt 代替 apt-get。)
一個缺點是它不會安裝最新版本。對於 Ubuntu 18.04.1,版本是 1.7.4,而截至 2018 年 8 月的最新版本是 1.8.4。對於 14.04,這個問題更嚴重,它安裝了 0.6.0,而截至 2016 年 2 月的最新版本是 1.7.4。
要使用 JsonCpp,請包含
#include <jsoncpp/json/json.h>
要編譯檔案,請新增標誌
-ljsoncpp
標頭檔案將被安裝到 /usr/include/jsoncpp/json。如果您好奇,庫檔案很可能被安裝到 /usr/lib/x86_64-linux-gnu(但您幾乎不需要知道它們的位置)。如果您想找到它,請嘗試
ls /usr/lib/*/*jsoncpp* ls /usr/lib/*jsoncpp*
要使用合併後的原始碼使用 JsonCpp,您無需下載或製作任何二進位制檔案。您將擁有一個 cpp 檔案和兩個 .h 檔案,您應該將它們包含到您的專案中。這些檔案將與系統無關。
- 從官方倉庫下載並解壓縮原始碼。轉到目錄。
- 執行
python amalgamate.py
它將建立三個檔案
dist/jsoncpp.cpp, the source file to be added to your project dist/json/json.h, the correspondent header file dist/json/json-forwards.h, which contains forward declarations of JSON types.
除了這三個檔案,您不需要任何其他東西。
- 從官方倉庫下載並解壓縮原始碼。轉到目錄。
- 安裝 cmake。在 Ubuntu 或 Debian Linux 的另一個版本下
sudo apt-get install cmake
- 建立構建目錄並進入它
mkdir -p build cd build
- 執行 cmake 命令
cmake -DCMAKE_BUILD_TYPE=release -DBUILD_STATIC_LIBS=ON -DBUILD_SHARED_LIBS=OFF -DARCHIVE_INSTALL_DIR=. -G "Unix Makefiles" ..
- 執行 make 命令
make
(您可以使用 -j 標誌來並行構建,例如 make -j 4。)
在 Unix 下,它將在您的構建目錄中建立檔案 src/lib_json/libjsoncpp.a。包含檔案將在 ../include/json 中。安裝檔案(make install 可能會有幫助),並使用
#include <jsoncpp/json/json.h>
和
-ljsoncpp
- 從官方倉庫下載並解壓縮原始碼。
- 在這個解壓縮的原始碼樹中,在 makefiles/msvc2010(對於 MS Visual Studio 2010)或 vs71(MS Visual Studio 2003)下,您將找到一些 Visual Studio 專案檔案,您可以對其進行升級和構建。
安裝 JsonCpp。
建立一個包含以下內容的檔案 alice.json
{
"book":"Alice in Wonderland",
"year":1865,
"characters":
[
{"name":"Jabberwock", "chapter":1},
{"name":"Cheshire Cat", "chapter":6},
{"name":"Mad Hatter", "chapter":7}
]
}
建立名為 alice.cpp 的檔案,內容如下
#include <iostream>
#include <fstream>
#include <jsoncpp/json/json.h> // or jsoncpp/json.h , or json/json.h etc.
using namespace std;
int main() {
ifstream ifs("alice.json");
Json::Reader reader;
Json::Value obj;
reader.parse(ifs, obj); // reader can also read strings
cout << "Book: " << obj["book"].asString() << endl;
cout << "Year: " << obj["year"].asUInt() << endl;
const Json::Value& characters = obj["characters"]; // array of characters
for (int i = 0; i < characters.size(); i++){
cout << " name: " << characters[i]["name"].asString();
cout << " chapter: " << characters[i]["chapter"].asUInt();
cout << endl;
}
}
編譯它
g++ -o alice alice.cpp -ljsoncpp
然後執行它
./alice
希望你會收到以下內容
Book: Alice in Wonderland
Year: 1865
name: Jabberwock chapter: 1
name: Cheshire Cat chapter: 6
name: Mad Hatter chapter: 7
所有內容都在 Json 名稱空間中。
類和其他型別的名稱使用大駝峰命名法(每個單詞的首字母大寫)。示例:Int、ArrayIndex、ValueType。成員函式、欄位和列舉值的名稱使用小駝峰命名法(除了第一個單詞外,每個單詞的首字母大寫)。示例:stringValue、isInt、size。
JsonCpp 執行大量的有效性檢查。如果操作無效,它將丟擲 std::runtime_error 異常,並附帶相關訊息。
JsonCpp 將每個數字儲存為 64 位整數(long long int 或 __int64),或 64 位無符號整數(unsigned long long int 或 unsigned __int64),或 double。下面,我們將分別稱它們為 int、uint 和 real。
陣列或物件最多可以包含 個元素。字串最多可以包含 個字元。物件鍵最多可以包含 個字元。
JsonCpp 提供了幾個輔助型別。
以下型別在 config.h 中定義
- Int - 定義為
int - UInt - 定義為
unsigned int - Int64 - 64 位有符號整數,在 Microsoft Visual Studio 中定義為
__int64,否則為long long int - UInt64 - 64 位無符號整數,在 Microsoft Visual Studio 中定義為
unsigned __int64,否則為unsigned long long int - LargestInt - 最大的可能的有符號整數,定義為
Int64 - LargestUInt - 最大的可能的無符號整數,定義為
UInt64
ArrayIndex 是陣列索引的型別。它被定義為 unsigned int,這意味著陣列或物件最多可以包含 個專案。
ValueType 是一個列舉,用於描述 JSON 值的型別。它被定義為
enum ValueType
{
nullValue = 0, ///< 'null' value
intValue, ///< signed integer value
uintValue, ///< unsigned integer value
realValue, ///< double value
stringValue, ///< UTF-8 string value
booleanValue, ///< bool value
arrayValue, ///< array value (ordered list)
objectValue ///< object value (collection of name/value pairs).
};
最簡單的輸入/輸出方式是透過 operator<< 和 operator>>。下面的程式從標準輸入讀取一個 JSON 值並將其寫入標準輸出。在發生語法錯誤的情況下,operator<< 將丟擲 runtime_error 異常。
#include <iostream>
#include <jsoncpp/json/json.h> // or something
using namespace std;
int main() {
Json::Value val;
cin >> val;
cout << val;
}
例如
$ g++ -o copy-json copy-json.cpp -ljsoncpp
$ echo '{"a":[1,2],"b":[3,4]}' | ./copy-json
{
"a" : [ 1, 2 ],
"b" : [ 3, 4 ]
}
為了以這種方式從字串中讀取資料,或者寫入字串,可以使用 std::istringstream 和 std::ostringstream,但還有其他方法可以做到這一點。
toStyledString 方法將任何值轉換為格式化的字串。它的宣告如下
std::string toStyledString() const;
另一種更穩健的讀取 JSON 值的方式是透過 Reader 類。它最實用的公共方法是(此處和以下,註釋是我的,方法的順序也是我的)
Reader(); // the default constructor
~Reader();
// Read a value from a JSON document and store it to root.
// If collectComments is true, comments are stored, otherwise they are ignored.
// In case of syntax error, it returns false, and the value of root may be arbitrary.
bool parse(const std::string& document, Value& root, bool collectComments = true); // from std::string
bool parse(const char *beginDoc, const char *endDoc, Value &root, bool collectComments=true); // from C-style string
bool parse(std::istream &is, Value &root, bool collectComments=true); // from input stream
// Returns a user friendly string that list errors in the parsed document.
std::string getFormattedErrorMessages() const;
示例
#include <iostream>
#include <jsoncpp/json/json.h> // or something
using namespace std;
int main() {
Json::Value val;
Json::Reader reader;
bool b = reader.parse(cin, val);
if (!b)
cout << "Error: " << reader.getFormattedErrorMessages();
else
cout << val;
}
與 Reader 不同,Writer 類是抽象類。有兩個類實現了它
- FastWriter 生成未格式化的、非人類可讀的文件。所有內容都將在一行中寫入。
- StyledWriter 生成格式化的、人類可讀的文件,類似於
operator<<,但縮排更少,沒有空行。
FastWriter 具有以下公共方法(預設建構函式和解構函式未顯示)
// omit the word "null" when printing null values
// this contradicts the JSON standard, but accepted by JavaScript
// this function is not available in old versions
void dropNullPlaceholders();
// don't add newline as last character
// this function is not available in old versions
void omitEndingLineFeed();
// print space after ":" in objects
void enableYAMLCompatibility();
// write JSON object to a string
virtual std::string write(const Value &root);
StyledWriter 具有以下公共方法(預設建構函式和解構函式未顯示)
virtual std::string write(const Value &root); // write JSON object to a string
最後,還有 StyledStreamWriter 類,用於寫入流。它被 operator<< 直接呼叫。該類不是 Writer 或任何其他類的子類。它的公共方法如下
StyledStreamWriter(std::string indentation="\t");
~StyledStreamWriter();
void write(std::ostream &out, const Value &root);
StyledStreamWriter 並不是很有用,因為 operator<< 更方便。如果需要非標準縮排,可以考慮使用它。
示例
#include <iostream>
#include <jsoncpp/json/json.h> // or something
using namespace std;
int main() {
Json::Value val;
cin >> val;
Json::FastWriter fast;
Json::StyledWriter styled;
string sFast = fast.write(val);
string sStyled = styled.write(val);
cout << "Fast:\n" << sFast << "Styled:\n" << sStyled;
cout << "Styled stream:\n";
Json::StyledStreamWriter styledStream;
styledStream.write(cout, val);
}
Value 的以下方法返回有關它的某些資訊
// get the type (intValue etc.)
ValueType type() const;
// get the number of elements in array or object (returns 0 for anything else, including string)
ArrayIndex size() const;
// returns true for empty array, empty object, or null
bool empty() const;
// returns true for null only
bool operator!() const;
// returns true for specific type only
bool isNull() const;
bool isBool() const;
bool isString() const;
bool isArray() const;
bool isObject() const;
// see explanations in text
bool isInt() const;
bool isInt64() const;
bool isUInt() const;
bool isUInt64() const;
bool isIntegral() const;
bool isDouble() const;
bool isNumeric() const;
isInt()、isInt64()、isUInt()、isUInt64() 僅在滿足以下所有條件時返回 true
- 型別為數字型別(int、uint 或 real)
- 如果型別為 real,則值應該沒有小數部分
- 值應該在給定型別的範圍內(分別為
Int、Int64、UInt、UInt64)
isDouble() 和 isNumeric() 當前在型別為 int、uint 或 real 時返回 true。
isIntegral() 對於 int 或 uint 始終返回 true。對於 real 值,如果該值沒有小數部分,並且在 Int64 或 UInt64 的範圍內,則返回 true。對於所有其他型別,它返回 false。
is... 函式不向後相容。在 0.* 版本中,isInt() 和 isUInt() 僅檢查型別,isInt64() 和 isUInt64() 不存在,isArray() 和 isObject() 也對 null 值返回 true,isIntegral 也對布林值返回 true 等等。
示例
#include <iostream>
#include <jsoncpp/json/json.h> // or something
using namespace std;
int main() {
Json::Value val;
cin >> val;
switch (val.type()) {
case Json::nullValue: cout << "nullValue\n"; break;
case Json::intValue: cout << "intValue\n"; break;
case Json::uintValue: cout << "uintValue\n"; break;
case Json::realValue: cout << "realValue\n"; break;
case Json::stringValue: cout << "stringValue\n"; break;
case Json::booleanValue: cout << "booleanValue\n"; break;
case Json::arrayValue: cout << "arrayValue\n"; break;
case Json::objectValue: cout << "objectValue\n"; break;
default: cout << "wrong type\n"; break;
}
}
要獲取數字、布林值或字串值本身,Value 類提供以下方法
const char* asCString() const;
std::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;
其中一些方法可能會丟擲 std::runtime_exception。一個簡單的規則:如果 isFoo() 返回 true,那麼呼叫 asFoo() 是安全的,但反過來不一定為真。
另一個規則,呼叫以下方法始終是安全的
asString()用於字串asLargestInt()用於 intasLargestUInt()用於 uintasFloat()或asDouble()用於任何數字(int、uint 或 real)asBool()用於布林值
以下是詳細資訊。
asInt()、asUInt、asInt64()、asUInt64()、asLargestInt()、asLargestUInt() 方法執行以下操作
- 如果原始值為數字,則檢查它是否在目標型別的範圍內。如果不是,則丟擲
std::runtime_error。然後將該值強制轉換為目標型別。強制轉換是簡單的,因此 real 值 3.9 傳送到asInt()後將變為 3。 - 如果原始值為布林值或 null,則返回 1 表示 true,0 表示 false,0 表示 null。
- 對於字串、陣列和物件,將丟擲
std::runtime_error。
asFloat() 和 asDouble() 方法執行以下操作
- 如果原始值為數字,則將其強制轉換為
float或double。 - 如果原始值為布林值或 null,則返回 1.0 表示 true,0.0 表示 false,0.0 表示 null。
- 對於字串、陣列和物件,將丟擲
std::runtime_error。
asBool() 方法接受任何內容。
- false、null、0、0.0 或空字串/陣列/物件將被轉換為
false - true、非零數字或非空字串/陣列/物件將被轉換為
true
asString()方法健壯、速度慢,屬於高階方法。它返回std::string。它能正確處理零字元的字串。它接受除陣列和物件之外的所有型別。對於 null,該方法返回"";對於布林值,它返回"true" 或 "false";對於數字,它返回其字串表示形式。對於陣列和物件,它丟擲std::runtime 異常。
asCString()方法是快速、低階方法。它只接受字串(否則會丟擲std::runtime 異常),並直接返回內部儲存的 C 風格字串。該方法不會分配任何內容。不要對返回的指標呼叫free() 或 delete[]!你需要記住兩點
- 由於 C 風格字串不能包含零字元,因此該方法只適合不包含零字元的字串。
- 對於空字串,它有時會返回 0。
如果你需要 C 風格字串,但不想被零字元搞混,JsonCpp 的較新版本添加了以下方法
bool getString(char const** begin, char const** end) const;
該方法將第一個字元的指標儲存到*begin,將最後一個零字元的指標儲存到*end,並返回true。對於非字串以及有時對於空字串,它返回false。
示例
#include <iostream>
#include <jsoncpp/json/json.h> // or something
using namespace std;
int main() {
Json::Value val;
cin >> val;
switch (val.type()) {
case Json::nullValue: cout << "null\n"; break;
case Json::intValue: cout << "int " << val.asLargestInt() << "\n"; break;
case Json::uintValue: cout << "uint " << val.asLargestUInt() << "\n"; break;
case Json::realValue: cout << "real " << val.asDouble() << "\n"; break;
case Json::stringValue: cout << "string " << val.asString() << "\n"; break;
/*
-or-
case Json::stringValue: {
const char *begin;
const char *end;
val.getString(&begin, &end);
cout << "string of length " << end - begin << "\n";
}
break;
*/
case Json::booleanValue: cout << "boolean " << val.asBool() << "\n"; break;
case Json::arrayValue: cout << "array of length " << val.size() << "\n"; break;
case Json::objectValue: cout << "object of length " << val.size() << "\n"; break;
default: cout << "wrong type\n"; break;
}
}
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 *beginValue, const char *endValue);
Value(const std::string &value);
Value(bool value);
Value(const Value &other);
第一個建構函式建立 null、false、0、0.0 或空字串/陣列/物件。其他建構函式不言自明。
還提供了賦值、交換和所有比較運算子(作為方法)。
Value &operator=(const Value &other);
void swap(Value &other);
bool operator<(const Value &other) const;
bool operator<=(const Value &other) const;
bool operator>=(const Value &other) const;
bool operator>(const Value &other) const;
bool operator==(const Value &other) const;
bool operator!=(const Value &other) const;
int compare(const Value &other) const;
陣列有自己的方法。這些方法也適用於 null。
其中一些類似於 C++ STL 的向量
ArrayIndex size() const;
bool empty() const;
void clear();
void resize(ArrayIndex size);
Value& operator[](ArrayIndex index);
Value& operator[](int index);
const Value& operator[](const ArrayIndex index) const;
const Value& operator[](const int index) const;
請注意,ArrayIndex 被定義為無符號整數。
resize() 透過刪除最後一個值或追加 null 值來更改陣列大小。
如果operator[] 接收負索引,它會丟擲std::runtime_error 異常。如果它接收等於或大於當前大小的index,
- 非常量
operator[]會追加index-size()+1個 null 值,然後返回最後一個值 - 常量
operator[]返回 null 值
要追加值,請使用append
Value &append(const Value &value);
這類似於 C++ 方法vector::push_back()。換句話說,foo.append(bar) 等同於foo[foo.size()]=bar。
get 方法返回第index 個元素,如果index 大於或等於大小,則返回defaultValue
Value get(ArrayIndex index, const Value &defaultValue) const;
請注意,它返回的值不是引用,因此呼叫該方法可能非常昂貴。
要檢查索引的有效性,你可能需要使用isValidIndex
bool isValidIndex(ArrayIndex index) const;
這不太有用,因為value.isValidIndex(index) 等同於index < value.size()。
你也可以使用removeIndex 刪除一個值
bool removeIndex(ArrayIndex i, Value* removed);
沒有奇蹟,該方法需要線性時間。如果i 大於或等於大小,它返回false。
如果foo 為 null,上面的方法將把它視為一個空陣列
foo.empty()返回truefoo.size()返回 0foo.clear()不做任何事foo.resize(0)不做任何事- 對於正數大小,
foo.resize(size)將foo轉換為包含size個 null 的陣列。 foo[i](非常量)將foo轉換為包含i+1個 null 的陣列,然後返回最後一個值foo[i](常量)返回 null 值foo.isValidIndex(i)始終返回falsefoo.get(index, defaultValue)始終返回defaultValuefoo.append(bar)使foo成為一個包含一個元素的陣列,該元素等於barfoo.removeIndex始終返回 false
clear()、empty() 和size() 方法也適用於物件。
除此之外,為既不是陣列也不是 null 的值呼叫以上任何方法都毫無用處。它們要麼返回一些瑣碎的值,要麼丟擲std::runtime_error 異常
foo.empty()返回false,除非foo是一個空物件foo.size()返回 0,除非foo是一個物件foo.clear()丟擲std::runtime_error異常,除非foo是一個物件resize、append、get、operator[]丟擲std::runtime_error異常isValidIndex始終返回falseremoveIndex始終返回false
物件有自己的方法。這些方法也適用於 null。
其中一些類似於 C++ STL 的對映
ArrayIndex size() const;
bool empty() const;
void clear();
Value& operator[](const char* key);
const Value& operator[](const char* key) const;
Value& operator[](const std::string& key);
const Value& operator[](const std::string& key) const;
這些不言自明。對於operator[],如果鍵不存在,非常量operator[] 會插入(鍵,null)對並返回該 null 的引用,而常量operator[] 只是返回某個 null 的引用。
以下方法將鍵作為 C++ 字串、C 字串或指定字串開頭和結尾的指標對來接收。最後一種形式在舊版本的 JsonCpp 中不存在。例如,如果字串包含零字元,它很有用。
isMember 方法檢查是否存在具有給定鍵的成員
bool isMember(const char* key) const;
bool isMember(const std::string& key) const;
bool isMember(const char* begin, const char* end) const; // only in newer versions
removeMember 方法刪除一個元素。前兩種形式返回被刪除的值而不是引用,這可能非常昂貴。
Value removeMember(const char* key); // deprecated in versions 1.*
Value removeMember(const std::string& key); // deprecated in versions 1.*
bool removeMember(const char* key, Value* removed); // only since versions 1.*
bool removeMember(std::string const& key, Value* removed); // only since versions 1.*
bool removeMember(const char* begin, const char* end, Value* removed); // only since versions 1.*
要遍歷物件的成員,你需要它們的鍵的完整列表。這是透過getMemberNames 完成的
Value::Members Value::getMemberNames() const;
Value::Members 被定義為
typedef std::vector<std::string> Members;
get 方法返回給定鍵的值,或者,如果不存在,則返回defaultValue。就像陣列一樣,它返回的值不是引用,因此呼叫該方法可能非常昂貴。
Value get(const char* key, const Value& defaultValue) const;
Value get(const char* begin, const char* end, const Value& defaultValue) const;
Value get(const std::string& key, const Value& defaultValue) const; // only in newer versions
find 方法只存在於較新版本中。它以(begin,end)形式接收鍵並返回指向找到的值的指標。如果未找到,它返回NULL 指標。
const Value* find(const char* begin, const char* end) const; // only in newer versions
上面的方法將 null 值視為一個空物件
clear()不做任何事size()返回 0empty()返回 true- 非常量
operator[]將值轉換為一個元素物件,具有給定的鍵和 null 值 - 常量
operator[]返回 null removeMember()返回 null(已棄用變體)或false(新變體)。getMemberNames()返回空的字串向量get()返回defaultValuefind()返回NULL
clear()、size()、empty() 方法也適用於陣列。除此之外,對於既不是 null 也不是物件的值,上面的方法會返回瑣碎的值或丟擲std::runtime_error 異常。
建立複雜結構
#include <iostream>
#include <jsoncpp/json/json.h> // or something
using namespace std;
int main() {
// create the characters array
Json::Value ch;
ch[0]["name"] = "Jabberwock";
ch[0]["chapter"] = 1;
ch[1]["name"] = "Cheshire Cat";
ch[1]["chapter"] = 6;
ch[2]["name"] = "Mad Hatter";
ch[2]["chapter"] = 7;
// create the main object
Json::Value val;
val["book"] = "Alice in Wonderland";
val["year"] = 1865;
val["characters"] = ch;
cout << val << '\n';
}
用於列印任何值的遞迴函式(當然,它已經存在,但我們從頭開始實現它)
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <jsoncpp/json/json.h> // or something
using namespace std;
void Indent(ostream& ofs, int indent) {
for (int i=0; i<indent; i++)
ofs << ' ';
}
void MyPrint(ostream& ofs, const Json::Value& val, int indent=0) {
switch (val.type()) {
case Json::nullValue: ofs << "null"; break;
case Json::booleanValue: ofs << (val.asBool() ? "true" : "false"); break;
case Json::intValue: ofs << val.asLargestInt(); break;
case Json::uintValue: ofs << val.asLargestUInt(); break;
case Json::realValue: ofs << val.asDouble(); break;
case Json::stringValue: ofs << '"' << val.asString() << '"'; break;
case Json::arrayValue: {
Json::ArrayIndex size = val.size();
if (size == 0)
ofs << "[]";
else {
ofs << "[\n";
int newIndent = indent + 4;
for (Json::ArrayIndex i=0; i<size; i++) {
Indent(ofs, newIndent);
MyPrint(ofs, val[i], newIndent);
ofs << (i + 1 == size ? "\n" : ",\n");
}
Indent(ofs, indent);
ofs << ']';
}
break;
}
case Json::objectValue: {
if (val.empty())
ofs << "{}";
else {
ofs << "{\n";
int newIndent = indent + 4;
vector<string> keys = val.getMemberNames();
for (size_t i=0; i<keys.size(); i++) {
Indent(ofs, newIndent);
const string& key = keys[i];
ofs << '"' << key << '"' << " : ";
MyPrint(ofs, val[key], newIndent);
ofs << (i + 1 == keys.size() ? "\n" : ",\n");
}
Indent(ofs, indent);
ofs << '}';
}
break;
}
default :
cerr << "Wrong type!" << endl;
exit(0);
}
}
int main() {
ifstream ifs("alice.json");
Json::Value val;
ifs >> val;
MyPrint(cout, val);
cout << '\n';
}
迭代器型別為Json::Value::iterator 和Json::Value::const_iterator。它們是雙向的,但不是隨機的。Json::Value 的方法是
const_iterator begin() const;
const_iterator end() const;
iterator begin();
iterator end();
只有陣列和物件具有非平凡的迭代器。如果foo 既不是陣列也不是物件,則foo.begin() 等於foo.end()。
迭代器具有完整的一組運算子:遞增和遞減(字尾和字首++ 和--)、等於和不等於比較、賦值、預設建構函式和複製建構函式。迭代器不是隨機的,因此無法將整數新增到迭代器。從另一個迭代器減去迭代器是可能的,但需要線性時間。
如果foo 是指向陣列的迭代器,則*foo 是對相應陣列元素的引用。如果foo 是指向物件的迭代器,則*foo 不是對(鍵,值)對的引用。它是對值的本身的引用。
operator-> 從版本 1.* 開始可用。
示例
#include <iostream>
#include <fstream>
#include <jsoncpp/json/json.h> // or something
using namespace std;
int main() {
Json::Reader reader;
Json::Value val;
reader.parse("{\"one\":1,\"two\":2,\"three\":3}", val);
for(Json::Value::const_iterator it=val.begin(); it!=val.end(); ++it)
cout << it->asInt() << '\n';
}
將列印
1
3
2
要接收鍵(對於指向物件的迭代器)或索引(對於指向陣列的迭代器),Json::Value::iterator 和Json::Value::const_iterator 提供了三種方法
// For iterator to array, returns the index
// For iterator to object, returs the key.
Value key() const;
// Return the index, or -1 if it is not an array iterator
UInt index() const;
// Return the key, or "" if it is not an object iterator.
const char *memberName() const;
如註釋中所解釋,key() 返回物件元素的鍵或陣列元素的索引;index() 返回陣列元素的索引,否則返回UInt(-1);memberName() 返回物件元素的鍵,否則返回空字串 ("")。
示例
這僅適用於較新版本。
#include <iostream>
#include <fstream>
#include <jsoncpp/json/json.h> // or something
using namespace std;
int main() {
Json::Reader reader;
Json::Value val;
reader.parse("{\"one\":1,\"two\":2,\"three\":3}", val);
for (Json::Value::const_iterator it=val.begin(); it!=val.end(); ++it)
cout << it.key().asString() << ':' << it->asInt() << '\n';
}
這將列印
one:1
three:3
two:2
對於舊版本,我們無法將 Json::Value::const_iterator 初始化為 Json::Value::iterator,並且沒有 operator->。
在 0.* 版本中,從 const_iterator 到 iterator 的轉換是不可能的,而相應的賦值是可能的。例如,如果 val 不是常量,我們無法編寫
Json::Value::const_iterator it = val.begin();
相反,我們應該使用 Json::Value::iterator。此外,沒有 operator->。
因此,我們應該用以下程式碼替換上面的程式碼
#include <iostream>
#include <fstream>
#include <jsoncpp/json/json.h> // or something
using namespace std;
int main() {
Json::Reader reader;
Json::Value val;
reader.parse("{\"one\":1,\"two\":2,\"three\":3}", val);
// We cannot declare "it" as a const_iterator, because begin() and end()
// return iterator, and there is no casting from iterator to const_iterator
for (Json::Value::iterator it=val.begin(); it!=val.end(); ++it)
cout << it.key().asString() << ':' << (*it).asInt() << '\n'; // no operator-> in this version
}