【C++】jsoncpp学习笔记(一)

00. 目录

01. JSON概述

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。它使得人们很容易的进行阅读和编写。同时也方便了机器进行解析和生成。它是基于 JavaScript Programming Language , Standard ECMA-262 3rd Edition - December 1999 的一个子集。 JSON采用完全独立于程序语言的文本格式,但是也使用了类C语言的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。这些特性使JSON成为理想的数据交换语言。

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。它是基于 JavaScript 的一种字符串格式,独立于编程语言,可以用来存储和传输数据。JSON 数据可以是简单的数字、字符串、数组或其他复杂数据类型。它通常用于 Web 应用程序中,用于存储和传输数据,也可以用于其他应用程序中。 JSON 格式由一系列特定的字符组成,这些字符称为“键”和“值”。键通常是字符串,值可以是字符串、数字、布尔值、数组或另一个 JSON 对象。在 JSON 中,数组和对象是通过花括号 [] 和 {} 包裹起来的,每个元素由逗号 , 分隔。 JSON 具有以下特点:

  • 简单易读:JSON 数据可以用简单的字符串表示,非常容易读取和编写。
  • 数据结构灵活:JSON 数据可以是各种数据类型,包括数字、字符串、数组和对象等。
  • 独立于语言:JSON 数据可以用于不同的编程语言,只需要一个 JSON 解析器。
  • 可读性高:JSON 数据可以被人类直接读取,不需要转换为其他格式。

JSON (JavaScript Object Notation) is a lightweight data interchange format that is easy for humans to read and write, and easy for machines to parse and generate. JSON is a widely used format for storing and exchanging data between web servers and clients. In JSON, data is represented as plain text in a human-readable format, with the structure of the data represented by a set of key-value pairs within the text. Each key-value pair is enclosed in curly braces {} and separated by a colon :.

02. JSON基本结构

JSON基于两种结构:

  • “名称/值”对的集合(A collection of name/value pairs)。不同的编程语言中,它被理解为对象(object),纪录(record),结构(struct),字典(dictionary),哈希表(hash table),有键列表(keyed list),或者关联数组 (associative array)。
  • 值的有序列表(An ordered list of values)。在大部分语言中,它被实现为数组(array),矢量(vector),列表(list),序列(sequence)。

这些都是常见的数据结构。目前,绝大部分编程语言都以某种形式支持它们。这使得在各种编程语言之间交换同样格式的数据成为可能。

03. jsoncpp概述

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,采用完全独立于编程语言的文本格式来存储和表示数据,常用于在客户端和服务器之间传输数据。

JSON由键值对组成,键必须是字符串,而值可以是字符串,布尔值,数组,对象或null

以下是一个简单的额JSON实例

在C/C++中,学生信息存储如下:

//在C/C++中,小明的信息如下
const char* name = "小明";
int age = 18;
float score[3] = {84.5, 90.5, 87};

使用JSON存储学生信息如下:

{
        "姓名" : "小明",
        "年龄" : 18,
        "成绩" : [84.5, 90.5, 87]
}

json数据类型:对象,数组,字符串,数字,布尔值,null

对象:使用大括号{ }括起来

数组:使用中括号[ ]括起来

字符串:使用双引号" "括起来

数字:包括整型和浮点型,直接使用,都视为数组

键和值之间使用冒号:分隔,不同键值对之间使用逗号,分隔。数组也可以存储对象,如下:

[
   {
        "姓名" : "小明",
        "年龄" : 18,
        "成绩" : [84.5, 90.5, 87]
   },
   {
        "姓名" : "小黑",
        "年龄" : 17,
        "成绩" : [88.5, 93, 85]
   }
]

jsoncpp是用于C++的JSON解析库,提供了简单易用的API来解析和生成JSON数据

最常用的是json格式的序列化和反序列化,完成将多个数据对象组织层json格式字符串,以及将json格式字符串解析得到多个数据对象的功能。

04. jsoncpp概览

jsoncpp库中的类被定义到了一个Json命名空间中,建议在使用这个库的时候先声明这个命名空间:

using namespace Json;

使用jsoncpp库解析json格式的数据,我们只需要掌握三个类:

Value 类:将json支持的数据类型进行了包装,最终得到一个Value类型
FastWriter类:将Value对象中的数据序列化为字符串
Reader类:反序列化, 将json字符串 解析成 Value 类型

05. Value类

Json::Value是JSON数据的通用类型。可以表示JSON对象,数组,字符串,数字,布尔值和null等各种类型。

这个类可以看做是一个包装器,它可以封装Json支持的所有类型,这样我们在处理数据的时候就方便多了。
在这里插入图片描述

//Json数据对象类
class Json::Value{
    //Value重载了[]和=,因此所有的赋值和获取数据都可以通过
    Value &operator=(const Value &other); 
    Value& operator[](const std::string& key);//示例:val["姓名"] = "小明";
    Value& operator[](const char* key);
    //移除元素
    Value removeMember(const char* key);
 
    //访问数组元素
    const Value& operator[](ArrayIndex index) const; //示例:val["成绩"][0]
    //添加数组元素
    Value& append(const Value& value);//示例:val["成绩"].append(88); 
    //获取数组元素个数
    ArrayIndex size() const;//示例:val["成绩"].size();
 
    //访问数据,以string类型返回
    std::string asString() const;//示例:string name = val["name"].asString();
    //访问数据,以const char*类型返回
    const char* asCString() const;//示例:char *name = val["name"].asCString();
    //访问数据,以int类型返回
    Int asInt() const;//示例:int age = val["age"].asInt();
    //访问数据,以float类型返回
    float asFloat() const;
    //访问数据,以bool类型返回
    bool asBool() 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(bool value);
Value(const Value& other);
Value(Value&& other);

检测数据类型

// 检测保存的数据类型
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;

将Value对象转换为实际类型

Int asInt() const;
UInt asUInt() const;
Int64 asInt64() const;
UInt64 asUInt64() const;
LargestInt asLargestInt() const;
LargestUInt asLargestUInt() const;
JSONCPP_STRING asString() const;
float asFloat() const;
double asDouble() const;
bool asBool() const;
const char* asCString() const;

对json数组的操作

ArrayIndex size() const;
Value& operator[](ArrayIndex index);
Value& operator[](int index);
const Value& operator[](ArrayIndex index) const;
const Value& operator[](int index) const;
// 根据下标的index返回这个位置的value值
// 如果没找到这个index对应的value, 返回第二个参数defaultValue
Value get(ArrayIndex index, const Value& defaultValue) const;
Value& append(const Value& value);
const_iterator begin() const;
const_iterator end() const;
iterator begin();
iterator end();

对json对象的操作

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);

// 通过key, 得到value值
Value get(const char* key, const Value& defaultValue) const;
Value get(const JSONCPP_STRING& key, const Value& defaultValue) const;
Value get(const CppTL::ConstString& key, const Value& defaultValue) const;

// 得到对象中所有的键值
typedef std::vector<std::string> Members;
Members getMemberNames() const;

将Value对象数据序列化为string

// 序列化得到的字符串有样式 -> 带换行 -> 方便阅读
// 写配置文件的时候
std::string toStyledString() const;

06. FastWriter类

class JSON_API FastWriter
    : public Writer {
public:
  FastWriter();
  ~FastWriter() override = default;

  void enableYAMLCompatibility();

  /** \brief Drop the "null" string from the writer's output for nullValues.
   * Strictly speaking, this is not valid JSON. But when the output is being
   * fed to a browser's JavaScript, it makes for smaller output and the
   * browser can handle the output just fine.
   */
  void dropNullPlaceholders();

  void omitEndingLineFeed();

public: // overridden from Writer
  String write(const Value& root) override;

private:
  void writeValue(const Value& value);

  String document_;
  bool yamlCompatibilityEnabled_{false};
  bool dropNullPlaceholders_{false};
  bool omitEndingLineFeed_{false};
};
// 将数据序列化 -> 单行
// 进行数据的网络传输
std::string Json::FastWriter::write(const Value& root);

07. Reader类

class JSON_API Reader {
public:
  using Char = char;
  using Location = const Char*;

  /** \brief An error tagged with where in the JSON text it was encountered.
   *
   * The offsets give the [start, limit) range of bytes within the text. Note
   * that this is bytes, not codepoints.
   */
  struct StructuredError {
    ptrdiff_t offset_start;
    ptrdiff_t offset_limit;
    String message;
  };

  /** \brief Constructs a Reader allowing all features for parsing.
    * \deprecated Use CharReader and CharReaderBuilder.
   */
  Reader();

  /** \brief Constructs a Reader allowing the specified feature set for parsing.
    * \deprecated Use CharReader and CharReaderBuilder.
   */
  Reader(const Features& features);

  /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
   * document.
   *
   * \param      document        UTF-8 encoded string containing the document
   *                             to read.
   * \param[out] root            Contains the root value of the document if it
   *                             was successfully parsed.
   * \param      collectComments \c true to collect comment and allow writing
   *                             them back during serialization, \c false to
   *                             discard comments.  This parameter is ignored
   *                             if Features::allowComments_ is \c false.
   * \return \c true if the document was successfully parsed, \c false if an
   * error occurred.
   */
  bool parse(const std::string& document, Value& root,
             bool collectComments = true);

  /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
   * document.
   *
   * \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[out] root            Contains the root value of the document if it
   *                             was successfully parsed.
   * \param      collectComments \c true to collect comment and allow writing
   *                             them back during serialization, \c false to
   *                             discard comments.  This parameter is ignored
   *                             if Features::allowComments_ is \c false.
   * \return \c true if the document was successfully parsed, \c false if an
   * error occurred.
   */
  bool parse(const char* beginDoc, const char* endDoc, Value& root,
             bool collectComments = true);

  /// \brief Parse from input stream.
  /// \see Json::operator>>(std::istream&, Json::Value&).
  bool parse(IStream& is, Value& root, bool collectComments = true);

  /** \brief Returns a user friendly string that list errors in the parsed
   * document.
   *
   * \return Formatted error message with the list of errors with their
   * location in the parsed document. An empty string is returned if no error
   * occurred during parsing.
   * \deprecated Use getFormattedErrorMessages() instead (typo fix).
   */
  JSONCPP_DEPRECATED("Use getFormattedErrorMessages() instead.")
  String getFormatedErrorMessages() const;

  /** \brief Returns a user friendly string that list errors in the parsed
   * document.
   *
   * \return Formatted error message with the list of errors with their
   * location in the parsed document. An empty string is returned if no error
   * occurred during parsing.
   */
  String getFormattedErrorMessages() const;

  /** \brief Returns a vector of structured errors encountered while parsing.
   *
   * \return A (possibly empty) vector of StructuredError objects. Currently
   * only one error can be returned, but the caller should tolerate multiple
   * errors.  This can occur if the parser recovers from a non-fatal parse
   * error and then encounters additional errors.
   */
  std::vector<StructuredError> getStructuredErrors() const;

  /** \brief Add a semantic error message.
   *
   * \param value   JSON Value location associated with the error
   * \param message The error message.
   * \return \c true if the error was successfully added, \c false if the Value
   * offset exceeds the document size.
   */
  bool pushError(const Value& value, const String& message);

  /** \brief Add a semantic error message with extra context.
   *
   * \param value   JSON Value location associated with the error
   * \param message The error message.
   * \param extra   Additional JSON Value location to contextualize the error
   * \return \c true if the error was successfully added, \c false if either
   * Value offset exceeds the document size.
   */
  bool pushError(const Value& value, const String& message, const Value& extra);

  /** \brief Return whether there are any errors.
   *
   * \return \c true if there are no errors to report \c false if errors have
   * occurred.
   */
  bool good() const;

private:
  enum TokenType {
    tokenEndOfStream = 0,
    tokenObjectBegin,
    tokenObjectEnd,
    tokenArrayBegin,
    tokenArrayEnd,
    tokenString,
    tokenNumber,
    tokenTrue,
    tokenFalse,
    tokenNull,
    tokenArraySeparator,
    tokenMemberSeparator,
    tokenComment,
    tokenError
  };
bool Json::Reader::parse(const std::string& document,
    Value& root, bool collectComments = true);
    参数:
        - document: json格式字符串
        - root: 传出参数, 存储了json字符串中解析出的数据
        - collectComments: 是否保存json字符串中的注释信息

// 通过begindoc和enddoc指针定位一个json字符串
// 这个字符串可以是完成的json字符串, 也可以是部分json字符串
bool Json::Reader::parse(const char* beginDoc, const char* endDoc,
    Value& root, bool collectComments = true);
	
// write的文件流  -> ofstream
// read的文件流   -> ifstream
// 假设要解析的json数据在磁盘文件中
// is流对象指向一个磁盘文件, 读操作
bool Json::Reader::parse(std::istream& is, Value& root, bool collectComments = true);

08. 附录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

沧海一笑-dj

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值