매우 간단한 json 래퍼 클래스
json을 써 볼까 싶은 생각에 찾아 보니 여러가지가 있지만 rapidjson이 괜찮은 듯해서 선택했다. 그런데 문제는 항상 반복하게 될 파일 열기. 그래서 이 부분만 간단히 처리할 클래스를 만들어 보았다. 즉 큰 기대는 금물.
입출력할 파일에 관한 정보를 굳이 멤버로 두지 않은 이유는 다음과 같다. 파일을 열고 읽는 멤버 함수를 만들고 보니 파일에 쓰는 멤버 함수도 있으면 좋을 것 같아 추가했다. 생성자에서 파일 이름을 받도록 하고 각 읽기/쓰기 멤버 함수에서 그대로 쓰면 괜찮겠는데, 생각해 보니 정보를 읽은 파일이 아니라 다른 파일에 기록할 수 있으면 더 좋을 것 같다. 결국 읽기/쓰기 멤버 함수도 파일을 받는 것과 안 받는 것 두 가지를 만들 수 있겠다. 즉 생성자에서 파일을 받으면 read()/write()를 사용해 읽고 쓰면 되고, 생성자에서 받지 않으면 read(file)/write(file)를 사용하면 된다.
그런데 생성자에서 파일을 받고 read()로 읽은 후 write(file)로 기록하거나 그 반대 상황, 또는 생성자와 멤버를 의도와 달리 섞어 쓴다면 클래스에 멤버로 있는 파일 정보는 어떻게 처리하는 게 좋을까. 그래서 내린 결론은 읽고 쓸 때 직접 지정하기로 했다. 헷갈릴 염려도 없고 가장 직관적이지 않을까.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | #ifndef JSON_H_ #define JSON_H_ #include "tstring.h" #include "thirdparty/rapidjson/document.h" class Json { public:   using Document = rapidjson::Document;   using SizeType = rapidjson::SizeType;   using Value = rapidjson::Value;   Json() {}   ~Json() {}   /**    * Read a json file.    * Read from the file specified in the parameter.    * @param file a json file included full path    * @return If succeeded return true, otherwise false    */   bool read(std::tstring const& file);   /**    * Write a json file.    * Write to the file specified in the parameter.    * @param file a json file included full path    * @return If succeeded return true, otherwise false    */   bool write(std::tstring const& file);   Document& document() {return document_;} private:   FILE* fp_ = nullptr;   rapidjson::Document document_; }; #endif | 
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | #include "json.h" #include "thirdparty/rapidjson/filereadstream.h" #include "thirdparty/rapidjson/filewritestream.h" #include "thirdparty/rapidjson/prettywriter.h" using std::tstring; using rapidjson::Document; using rapidjson::FileReadStream; using rapidjson::FileWriteStream; using rapidjson::PrettyWriter; const int kReadBufferSize = 65536; bool Json::read(std::tstring const& file) {   errno_t err = ::_tfopen_s(&fp_, file.c_str(), _T("rb"));   if (err) {     return false;   }   char readBuffer[kReadBufferSize];   FileReadStream readStream(fp_, readBuffer, _countof(readBuffer));   bool result = !document_.ParseStream(readStream).HasParseError();   ::fclose(fp_);   return result; } bool Json::write(std::tstring const& file) {   errno_t err = ::_tfopen_s(&fp_, file.c_str(), _T("wb"));   if (err) {     return false;   }   char writeBuffer[kReadBufferSize];   FileWriteStream writeStream(fp_, writeBuffer, _countof(writeBuffer));   PrettyWriter<FileWriteStream> writer(writeStream);   document_.Accept(writer);   ::fclose(fp_);   return true; } | 
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | #include <iostream> #include "json.h" int _tmain(int argc, _TCHAR* argv[]) {   std::tstring fileName = _T("sample.json");   Json json;   json.read(fileName.c_str());   Json::Document& doc = json.document();   Json::Value& gem = doc["a"];   for (Json::SizeType i = 0; gem.Size() != i; ++i) {     std::cout << gem[i]["id"].GetInt() << std::endl;     std::cout << gem[i]["name"].GetString() << std::endl;     std::cout << gem[i]["max"].GetDouble() << std::endl;     gem[i]["name"] = "mod";   }   json.write(fileName.c_str());   return 0; } | 
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | {     "a": [         {             "id": 1,             "name": "abc",             "max": 324.22         },         {             "id": 2,             "name": "bcd",             "max": 43242         }     ],     "b": [         {             "id": 1,             "name": "bbc"         },         {             "id": 2,             "name": "bac"         }     ] } | 
rapidjson 관련 파일 경로를 적절히 바꾸고 컴파일하면 std::tstring 때문에 오류가 발생할 텐데 간단히 std::string으로 바꾸면 된다. 실행하면 파일을 읽어 화면 출력 후 배열 a에 대한 각 요소 이름을 mod로 바꿔 다시 저장한다.
그런데 딱히 프로그램 외부에서 정보를 계속 바꿔 가며 사용할 일이 없다 보니 이걸 써야 할까 말아야 할까 아직도 고민 중인 게 함정.
 
																			 
																			