添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
  • Loading JSON array from file
  • Adding a new object to the existing list
  • Saving the list to a new file
  • Useful resources
  • Introduction

    In my previous article, I covered serializing/deserializing JSON in C++ to a simple object using RapidJSON .

    When working with JSON, my goal is to work always with object models and keep the actual JSON parsing behind the scenes. This keeps the readability and maintainability of the code as JSON manipulation, type checking and exception handling is done is a single class and not across the entire application. This also enables a future replacement of the JSON parsing library without the need to change the code of the entire application.

    My stack

  • Visual Studio 2019 Community Edition, 16.5.1
  • RapidJSON 1.1.0 release
  • Windows 10 Pro 64-bit (10.0, Build 18363)
  • Preparing the project

  • I am going to use the same C++ Console Application from the previous post about JSON Serialization in C++ .
  • My JSON will be an array of products in an inventory. Here is the sample of 3 products in inventory:
  • 3 "id" : 1 , 4 "name" : "Bush Somerset Collection Bookcase" , 5 "category" : "Furniture" , 6 "sales" : 22.0 7 }, 9 "id" : 2 , 10 "name" : "Mitel 5320 IP Phone VoIP phone" , 11 "category" : "Technology" , 12 "sales" : 907.1519775390625 13 }, 14 { 15 "id" : 3 , 16 "name" : "Poly String Tie Envelopes" , 17 "category" : "Office Supplies" , 18 "sales" : 3.2639999389648439 19 }

    Creating the object models

    For the single product, we used the following object model:

  • We added member variable for every JSON property with the correct type (id, name, sales, category)
  • Implemented getters/setters
  • Implemented Serialize and Deserialize functions
  •  1namespace JSONModels
     3  class Product : public JSONBase
     5  public:
     6    Product();		
     7    virtual ~Product();			
     9    virtual bool Deserialize(const rapidjson::Value& obj);
    10    virtual bool Serialize(rapidjson::Writer<rapidjson::StringBuffer>* writer) const;
    12    // Getters/Setters.
    13    const std::string& Name() const { return _name; }
    14    void Name(const std::string& name) { _name = name; }
    16    const std::string& Category() const { return _category; }
    17    void Category(const std::string& category) { _category = category; }
    19    float Sales() const { return _sales; }
    20    void Sales(float sales) { _sales = sales; }
    22    int Id() const { return _id; }
    23    void Id(int id) { _id = id; }		
    24  private:
    25    std::string _name;
    26    std::string _category;
    27    float _sales;
    28    int _id;
    29  };	
    

    In the next step, we need to create a class that will hold a list of Product objects.

     1namespace JSONModels
     3  class Products : public JSONBase
     5  public:		
     6    virtual ~Products() {};
     7    virtual bool Deserialize(const std::string& s);		
     9    // Getters/Setters.
    10    std::list<Product>& ProductsList() { return _products; }
    11  public:
    12    virtual bool Deserialize(const rapidjson::Value& obj) { return false; };
    13    virtual bool Serialize(rapidjson::Writer<rapidjson::StringBuffer>* writer) const;
    14  private:
    15    std::list<Product> _products;
    16  };
    

    Serialize

    This function is called by JSONBase class once the object is being serialized. Our list is stored in the memory, so we need to write it to the StringBuffer .

    In this code, we iterate over all Product in our _product list and call for Serialize function of the Product class.

     1bool Products::Serialize(rapidjson::Writer<rapidjson::StringBuffer>* writer) const
     3  writer->StartArray();
     5     for (std::list<Product>::const_iterator it = _products.begin(); it != _products.end(); it++)
     7        (*it).Serialize(writer);
     9  writer->EndArray();
    11  return true;
    

    Deserialize

    Deserialize function is called by JSONBase class with JSON string parameter.

  • First we need to call for InitDocument function to parse the string
  • Once the doc object is initialized, we need to iterate over all JSON objects, call for Deserialize and finally add to _products list.
  •  1bool Products::Deserialize(const std::string& s)
     3  rapidjson::Document doc;
     4  if (!InitDocument(s, doc))
     5    return false;
     7  if (!doc.IsArray())
     8    return false;
    10  for (rapidjson::Value::ConstValueIterator itr = doc.Begin(); itr != doc.End(); ++itr)
    11  {
    12    Product p;
    13    p.Deserialize(*itr);
    14    _products.push_back(p);
    15  }
    17  return true;
    

    Usage

    Loading JSON array from file

     1// load json array
     2JSONModels::Products products;
     3products.DeserializeFromFile("DataSampleArray.json");
     5for (std::list<JSONModels::Product>::const_iterator it = products.ProductsList().begin();
     6  it != products.ProductsList().end(); it++)
     8  // print some values.
     9  printf("Name:%s, Sales:%.3f", (*it).Name().c_str(), (*it).Sales());
    

    Adding a new object to the existing list

    1// add new product
    2JSONModels::Product newProduct;
    3newProduct.Id(101);
    4newProduct.Name("Global Value Mid-Back Manager's Chair, Gray");
    5newProduct.Category("Furniture");
    6newProduct.Sales(213.115f);    
    7products.ProductsList().push_back(product);
    

    Saving the list to a new file

    1// save to new array file.
    2products.SerializeToFile("DataSampleArrayNew.json")
    

    Useful resources

  • Full source code of this post in GitHub
  •