目录
Json是一种轻量级的数据交互格式,易于阅读和编写,也易于机器解析和生成。
Json基本结构
键:必须是字符串。
值:可以是字符串、数字、对象、数组、布尔值、null。
键值对:"key" : value 。
对象:由键值对组成,使用{ }括住,多个键值对之间用逗号,分隔开。
数组:由值的有序集合组成,使用[ ]括住,多个值之间用逗号,隔开。
json数据格式示例:
javascript
{
"address" :
{
"city" : "xi'an",
"country" : "china"
},
"age" : 22,
"is_student" : true,
"name" : "skk",
"sex" : "male",
"skills" : [ "c++", "linux", "mysql" ]
}
JsonCpp库
JsonCpp是一个高性能的Json库,用于处理数据,它提供完整的Json标准支持,包括解析Json字符串、生成Json字符串,读写Json对象和数组等功能。
特点
易于使用:JsonCpp提供了简单直观的API,使得在C++程序中处理Json数据变得容易。
高性能:快速生成和解析大量解析Json数据。
跨平台:支持多种操作系统,包括:Windows、Linux和macOS。
无依赖:JsonCpp不依赖其他外库,可以轻松集成到C++项目中。
完全支持C++11:支持智能指针。
安装指令(ubuntu下)
bash
sudo apt install libjsoncpp-dev
头文件包含:
cpp
#include <jsoncpp/json/json.h>
注意:使用g++编译时要加上-ljsoncpp选项(l使小写L)。
中间转储类型Json::Value
Json::Value类型对象,不管是将数据进行序列化和反序化都要经过Json::Value类型对象。
Json序列化:将对象数据存储到Value对象中,然后数据就被转换为Json格式的数据。
Json反序列化:将Json格式数据存储到Value对象中,然后从Value对象中得到对象数据。
jsoncpp库部分源码
cpp
//Json::Value部分源码
namespace Json {
class JSON_API Value {
Int asInt() const;
UInt asUInt() const;
Int64 asInt64() const;
UInt64 asUInt64() const;
float asFloat() const;
double asDouble() const;
bool asBool() const;
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;
//Number of values in array or object
ArrayIndex size() const;
bool empty() const;
bool operator!() const;
void clear();
void resize(ArrayIndex size);
Value& operator[](ArrayIndex index);
Value& operator[](int index);
const Value& operator[](ArrayIndex index) const;
const Value& operator[](int index) const;
/// If the array contains at least index+1 elements, returns the element
/// value,
/// otherwise returns defaultValue.
Value get(ArrayIndex index, const Value& defaultValue) const;
/// Return true if index < size().
bool isValidIndex(ArrayIndex index) const;
/// Append value to array at the end.
/// Equivalent to jsonvalue[jsonvalue.size()] = value;
Value& append(const Value& value);
};
}
cpp
//wirter.h
namespace Json {
class Value;
/**
Usage:
\code
using namespace Json;
void writeToStdout(StreamWriter::Factory const& factory, Value const& value) {
std::unique_ptr<StreamWriter> const writer(
factory.newStreamWriter());
writer->write(value, &std::cout);
std::cout << std::endl; // add lf and flush
}
\endcode
*/
class JSON_API StreamWriter {
virtual int write(Value const& root, JSONCPP_OSTREAM* sout) = 0;
class JSON_API Factory {
public:
virtual StreamWriter* newStreamWriter() const = 0;
}; // Factory
}; // StreamWriter
class JSON_API StreamWriterBuilder : public StreamWriter::Factory {
public:
Json::Value settings_;
StreamWriterBuilder();
~StreamWriterBuilder() JSONCPP_OVERRIDE;
/**
* \throw std::exception if something goes wrong (e.g. invalid settings)
*/
StreamWriter* newStreamWriter() const JSONCPP_OVERRIDE;
}
cpp
//reaser.h
class JSON_API CharReader {
public:
virtual ~CharReader() {}
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
document.
* The document must be a UTF-8 encoded string containing the document to read.
*
* \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the
document to read.
* \param endDoc Pointer on the end of the UTF-8 encoded string of the
document to read.
* Must be >= beginDoc.
* \param root [out] Contains the root value of the document if it was
* successfully parsed.
* \param errs [out] Formatted error messages (if not NULL)
* a user friendly string that lists errors in the parsed
* document.
* \return \c true if the document was successfully parsed, \c false if an
error occurred.
*/
virtual bool parse(
char const* beginDoc, char const* endDoc,
Value* root, JSONCPP_STRING* errs) = 0;
class JSON_API Factory {
public:
virtual ~Factory() {}
/** \brief Allocate a CharReader via operator new().
* \throw std::exception if something goes wrong (e.g. invalid settings)
*/
virtual CharReader* newCharReader() const = 0;
}; // Factory
}; // CharReader
/** \brief Build a CharReader implementation.
Usage:
\code
using namespace Json;
CharReaderBuilder builder;
builder["collectComments"] = false;
Value value;
JSONCPP_STRING errs;
bool ok = parseFromStream(builder, std::cin, &value, &errs);
\endcode
*/
class JSON_API CharReaderBuilder : public CharReader::Factory {
public:
Json::Value settings_;
CharReaderBuilder();
~CharReaderBuilder() JSONCPP_OVERRIDE;
CharReader* newCharReader() const JSONCPP_OVERRIDE;
};
序列化示例
cpp
#include <iostream>
#include <sstream>
#include <memory>
#include <jsoncpp/json/json.h>
int main()
{
Json::Value val;
val["name"] = "skk";
val["age"] = 22;
val["sex"] = "male";
val["is_student"] = true;
val["skills"].append("c++");
val["skills"].append("linux");
val["skills"].append("mysql");
Json::Value obj;
obj["country"] = "china";
obj["city"] = "xi'an";
val["address"] = obj;
Json::StreamWriterBuilder builder;
builder["indentation"] = ""; // 缩进空格数,默认是2个空格,设置为""表示不缩进
//builder["commentStyle"] = "None";// 注释风格,默认是"All",设置为"None"表示不注释
std::unique_ptr<Json::StreamWriter> writer(builder.newStreamWriter());
std::stringstream ss;
writer->write(val, &ss);
//std::cout << std::endl;
//std::cout << ss.str() << std::endl;
}
反序列化示例
cpp
int main()
{
std::string str = R"({
"name": "skk",
"age": 22,
"sex": "male",
"is_student": true,
"skills": [
"c++",
"linux",
"mysql"
],
"address": {
"country": "china",
"city": "xi'an"
}
})";
Json::Value val;
Json::CharReaderBuilder builder;
std::string err = "";
std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
reader->parse(&str[0], &str[str.size()], &val, &err);
if (!err.empty()) {
std::cout << "parse error: " << err << std::endl;
}
if(!val["name"].isNull()){
std::cout << "name: " << val["name"].asString() << std::endl;
}
if(!val["age"].isNull()){
std::cout << "age: " << val["age"].asInt() << std::endl;
}
if(!val["sex"].isNull()){
std::cout << "sex: " << val["sex"].asString() << std::endl;
}
if(!val["is_student"].isNull()){
std::cout << "is_student: " << val["is_student"].asBool() << std::endl;
}
if(!val["skills"].isNull()){
for(int i = 0; i < val["skills"].size(); i++){
std::cout << "skill: " << val["skills"][i].asString() << std::endl;
}
}
if(!val["address"].isNull()){
std::cout << "country: " << val["address"]["country"].asString() << std::endl;
std::cout << "city: " << val["address"]["city"].asString() << std::endl;
}
return 0;
}