rapidjson查询操作基本用法

博客搬家,原地址: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);
}

猜你喜欢

转载自blog.csdn.net/u014630623/article/details/89020039