欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

rapidjson查询操作基本用法

程序员文章站 2024-02-02 18:31:16
...

博客搬家,原地址:https://langzi989.github.io/2017/05/27/rapidjson查询操作基本用法/

本系列文章以例子的方式进行呈现。

#include "rapidjson/document.h"
#include <iostream>

int main()
{
  const char* test = "{\"num\":123, \"hello\":null, \"type\": \"object\",\"properties\": {\"oid\": {\"type\": \"string\"}, \"username\": {\"type\": \"string\"},\"creid\": {\"type\": \"string\"}},\"required\": [\"oid\", \"username\",\"creid\"]}";
  rapidjson::Document document;
  //Parse(const char*). 从c-string解析为Document json格式
  document.Parse(test);

  //GetString().从Document json中取出string
  std::cout << "type = " << document["type"].GetString() << std::endl;

  /*  函数原型          函数功能
  *   IsNull()       判断当前键对应的值是不是null
  *   IsNumber()     判断当前键对应的值是不是number
  *   IsInt()        判断当前键对应的值是不是int
  *   IsDouble()     判断当前键对应的值是不是double
  *   IsString()     判断当前键对应的值是不是string
  *   IsBool()       判断当前键对应的值是不是bool
  *   IsArray()      判断当前键对应的值是不是array
  *   ...
  */
  std::cout << "hello is " << (document["hello"].IsNull() ? "null" : "not null") << std::endl;
  std::cout << "num is " << (document["num"].IsNumber() ? "number" : "not number") << std::endl;
  std::cout << "required is " << (document["required"].IsArray()? "array" : "not array") << std::endl;

  /*      访问Array的两种方法
  *    1. 通过下标访问    //使用引用来连续访问,方便之余还更高效。
  *    2. 通过迭代器访问
  *        注意问题
  *    1.索引使用SizeType类型,而不是size_t类型,缺省情况下,SizeType是unsigned的typedef
  *    2.对于String类型使用GetInt是非法的,这个时候会导致程序崩溃
  */
  const rapidjson::Value &a = document["required"];
  assert(a.IsArray());
  for (rapidjson::SizeType i = 0; i < a.Size(); i++)
    std::cout << a[i].GetString() << std::endl;
  for (rapidjson::Value::ConstValueIterator it = a.Begin(); it != a.End(); it++) {
    std::cout << it->GetString() << std::endl;
    std::cout << it->GetStringLength() << std::endl;
  }

  /*        访问object的方法
  *    1.使用迭代器进行访问
  *    2.使用键对应的下标进行当问 如:document["required"]
  *          注意问题
  *    1.在使用下标访问之前,最好先调用HasMember()检查一下当前键是否存在,若存在再往下继续。否则会出现段错误。
  */
  static const char* kTypeNames[] = {"Null", "False", "True", "Object", "Array", "String", "Number"};
  for (rapidjson::Value::ConstMemberIterator it = document.MemberBegin();
        it != document.MemberEnd(); it++) {
        std::cout << it->name.GetString() << " is type : " << kTypeNames[it->value.GetType()] << std::endl;;
  }

  /*        查询Number
  *      说明:Json只提供一种数值类型---Number。Number可以是实数也可以是整数
  *           Dom提供了5中数值类型。包括unsigned,int,uint_64,int_64,double
  *         类型检查          数值提取
  *        IsUint()          GetUint()
  *        IsInt()           GetInt()
  *        IsUint64()        GetUint64()
  *        IsInt64()         GetInt64()
  *        IsDouble()        GetDouble()
  *
  *       查询String
  *     说明:除了getString(), Value类也有一个GetStringLength();原因是rapidjson的String需要支持Unicode字符,如\u0000.问题是C/C++字符串是
  *         空字符结尾的字符串,,这种字符串会把'\0'作为结束符号。为了符合RFC4627,若要处理这些带有unicode的字符串,
  *         需要使用GetStringLength获取正确的字符串长度
  *       函数                                功能
  *     const char* getString()             获取C字符串
  *     SizeType GetStringLength()const     获取字符串的长度,
  */

  rapidjson::Document d1;
  d1.Parse("{\"s\":\"a\\u0000b\", \"num\":123}");
  std::cout << d1["s"].GetString() << std::endl;
  std::cout << d1["s"].GetStringLength() << std::endl;
  std::cout << strlen(d1["s"].GetString()) << std::endl;

  /*
  *       比较两个Value的值
  *     1.使用==和!=比较两Value的值,当且仅当两个Value的类型和内容相等才算相等。
  *     2.可以将Value与原始值进行比较
  *     3.若被比较的两个Value的类型不同,直接返回false。
  *     4.可以比较不同Object的值
  */

  std::cout << (document["num"] == document["hello"]) << std::endl;
  std::cout << (document["num"] == d1["num"]) << std::endl;

  /*
  *           创建/修改值
  *       1.改变Value的类型:当使用默认构造函数创建一个Value或者Document的时候,它的类型默认为
  *         NULL,要改变其类型,使用SetXXX()。如
  *                             rapidjsons::Document d;
  *                             d.SetObject(); //将d的类型修改为Object
  *                             rapidjson::Value v;
  *                             v.SetInt(1); //或者v = 1;
  *       2.构造函数的重载
  *                              rapidjson::Value b(false);
  *                              rapidjson::Value n(10);
  *
  *       3.特别注意Value的转移语义。 Value重载operator=()时使用了转移语义。
  *                              rapidjson::Value a(123);
  *                              rapidjson::Value b(456);
  *                              a = b; //此时b变为null,a为456
  *       4.使用move()函数实现函数参数中的转移语义
  *                              rapidjson::Value a(0);
  *                               test(a.move());
  *
  */

  rapidjson::Value testa(10);
  rapidjson::Value testb(10);
  testa = testb;
  std::cout << testa.GetInt() << std::endl;
  if (testb.IsNull())
  {
    std::cout << "testb is moved to a, and now testb is null" << std::endl;
  }
  else
  {
    std::cout << testb.GetInt() << std::endl;
  }

  /*
  *                创建String
  *         rapidjson提供两种string的存储策略:
  *                       1.copy-string(深拷贝):分配缓冲区,然后把来源数据复制至它
  *                       2.const-string(浅拷贝):简单的存储字符串指针
  *          说明:
  *               1.copy-string总是安全的,因为它拥有数据的克隆
  *               2.当数据源发生改变,const-string中的数据也会受到影响
  *         上面两种字符串的创建方式:
  *               1.copy-string创建方式需要给API传递一个Allocator参数,这个做法避免了给每一个
  *                             Value都保存一个Allocator。另外还需要一个length参数,保存长度信息,故
  *                             此函数可以处理带有空字符的字符串。
  *               2.const-string创建方式不需要长度信息和Allocator参数,它默认字符串以\0结束.
  *                              一般用于常量字符串或者具有安全生存周期的字符串上
  */

  rapidjson::Value autor;
  char buffer[50];
  int len = sprintf(buffer, "%s %s", "Milo", "Yip");
  autor.SetString(buffer,len, document.GetAllocator());
  memset(buffer, 0x0, sizeof(buffer));
  std::cout << autor.GetString() << std::endl;

  rapidjson::Value testString;
  testString = "testString";
  std::cout << testString.GetString() << std::endl;

  /**                   修改Array
  *           函数                                                              功能
  *        clear()                                                      清空Array中的内容
  *        Reserve(SizeType, Allocator&)                                申请指定大小空间,单不插入数据
  *        Value& PushBack(Value&, Allocator&)                          添加元素
  *        template <typename T> GenericValue& PushBack(T, Allocator&)  添加元素
  *        Value& PopBack()                                             删除最后一个元素
  *        ValueIterator Erase(ConstValueIterator pos)                  删除指定位置元素
  *        ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) 删除指定范围元素
  */

  rapidjson::Value testArray(rapidjson::kArrayType);
  rapidjson::Document::AllocatorType& testAllocator = document.GetAllocator();

  for (int i = 0; i < 5; i++)
  {
    testArray.PushBack(i, testAllocator);
  }

  testArray.PushBack("lua", testAllocator).PushBack("Mio", testAllocator);

  for (rapidjson::SizeType i = 0;i < 5; i++)
    std::cout <<  testArray[i].GetInt() << std::endl;
  std::cout << testArray[5].GetString() << std::endl;
  std::cout << testArray[6].GetString() << std::endl;

  /*                      修改Object
  *     说明:每个Object都是键值对的集合。每个键必须为String。
  *     添加成员的函数:
  *                   1.Value& AddMember(Value&, Value&, Allocator& allocator)
  *                   2.Value& AddMember(StringRefType, Value&, Allocator&)
  *                   3.template <typename T> Value& AddMember(StringRefType, T value, Allocator&)
  *
  *     补充说明:1.使用StingRefType作为name参数的重载版本与字符串的SetString()类似。这些重载是为了避免复制name字符串
  *               因为jsonObject中经常会使常数键名。
  *              2.如果你需要从非常数字符串或者生命周期不足的字符串创建键名,需要使用copy-string API。
  *                 为了避免中间变量,可以使用临时值
  *
  *     移除成员函数:
  *             1.bool RemoveMember(const Ch* name):使用键名来移除成员(线性时间复杂度)。
  *             2.bool RemoveMember(const Value& name):除了 name 是一个 Value,和上一行相同。
  *             3.MemberIterator RemoveMember(MemberIterator):使用迭代器移除成员(_ 常数 _ 时间复杂度)。
  *             4.MemberIterator EraseMember(MemberIterator):和上行相似但维持成员次序(线性时间复杂度)。
  *             5.MemberIterator EraseMember(MemberIterator first, MemberIterator last):移除一个范围内的成员,维持次序(线性时间复杂度)。
  */

  rapidjson::Value contact(rapidjson::kObjectType);
  contact.AddMember("name", "milo", document.GetAllocator());
  contact.AddMember("married", false, document.GetAllocator());

  std::cout << "contact[name] is:"<<contact["name"].GetString() << std::endl;
  std::cout << "contact[married] is:" << contact["married"].GetBool() << std::endl;

  contact.AddMember(rapidjson::Value("copy", document.GetAllocator()).Move(), // copy string
                  rapidjson::Value().Move(),                                // null value
                  document.GetAllocator());

  /*                        深复制Value
  *           方法:
  *                   1.含有Allocator的构造函数
  *                   2.含有Allocator的CopyFrom
  *                           交换Value
  *            方法:  Swap() 无论两颗Dom树多复杂,交换时间为常数
  */

  rapidjson::Value testCopy1(123);
  rapidjson::Value testCopy2(testCopy1, document.GetAllocator());
  rapidjson::Value testCopy3;
  testCopy3.CopyFrom(testCopy1, document.GetAllocator());

  testCopy1.Swap(testCopy3);
}
相关标签: rapidjson