C++ Builder XE4 > JSON > TStringGridのJSONファイル保存 > TJSONArrayを使用

```txt:動作環境
C++ Builder XE4
秀丸エディタ Version 8.79
```

### 処理概要

- TStringGridに項目と値が入っている
    - 項目は横に並ぶ
    - 複数データは縦に並ぶ
- JSONファイルに保存する

### 参考

- [JSON with RadStudio Delphi or C++ Builder](http://chapmanworld.com/2015/01/18/json-with-radstudio-delphi-or-c-builder/) by CRAIG CHAPMAN

C++ Builder実装を参考にしました。

### データ

`#include`にて.csv定義したファイルを使います。

- [Link > Wandbox:ファイルを読込みできる | C言語:includeにてcsvファイルを配列として読込む](https://qiita.com/7of9/items/33bc206915aed19e9a50)
- [comment by @tenmyoさん](https://qiita.com/7of9/items/30188d50e33df6c35066#comment-6427418db7aaf4e7b98c)
- [c++ builder XE4, 10.2 Tokyo > .csvからリストをstatic const String[]へ読取り / "//"でコメントアウトもできる](https://qiita.com/7of9/items/cb2fdeba5ad0d232311e)

例:

```data180419.csv
"name", "age", "type",
"7of9", "120", "borg",
"Janeway", "40", "human",
"Odo", "250", "shapeShifter",
```

上記のファイルは「プロジェクトファイル(.cbproj)」が置いているファイルに用意します。

### code v0.1

```Unit1.h
//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.Grids.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// IDE で管理されるコンポーネント
	TStringGrid *StringGrid1;
	TButton *B_toJSON;
	void __fastcall B_toJSONClick(TObject *Sender);
private:	// ユーザー宣言
	void __fastcall makeTestData(void);
public:		// ユーザー宣言
	__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
```

```Unit1.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include <DBXJSON.hpp> // for JSON
#include <memory> // for unique_ptr
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------

/*
v0.1 Apr. 19, 2018
  - add B_toJSONClick()
	+ JSONArrayでファイル書込み
  - add [kGroupName]
  - add [kSaveFile]
  - add makeTestData()
  - add kTitileAndData[][]
  - add [NUM_ITEM]
*/


__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
	makeTestData();
}
//---------------------------------------------------------------------------
// StringGridへのテストデータ作成
//
#define NUM_ITEM (3)  // 項目数 (例: 3 for "name, age, type")

// StringGrid用データ
static const String kTitileAndData[][NUM_ITEM] =
{
#include "data180419.csv"
};

void __fastcall TForm1::makeTestData(void)
{
	StringGrid1->FixedRows = 1; // タイトルは1行
	StringGrid1->FixedCols = 0; // 固定列はなし
	StringGrid1->ColCount = NUM_ITEM;

	int rowCnt = sizeof(kTitileAndData) / sizeof(kTitileAndData[0]);

	for(int ri=0; ri < rowCnt; ri++) {  // ri: row index
		for(int ci=0; ci < NUM_ITEM; ci++) {  // ci: column index
			StringGrid1->Cells[ci][ri] = kTitileAndData[ri][ci];
		}
	}

}
//---------------------------------------------------------------------------
// JSON処理

static const String kSaveFile = L"out180419.JSON";  // 出力ファイル
static const String kGroupName = L"member";  // TJSONArrayを格納するグループ名

void __fastcall TForm1::B_toJSONClick(TObject *Sender)
{
	// 1. JSON用意
	TJSONObject *json = new TJSONObject();  // ファイル保存用JSON
	TJSONArray *jary = new TJSONArray();  // グループ用JSONArray

	json->AddPair(kGroupName, jary);

	TJSONObject *member;  // グループ内のメンバー用JSON
	for(int ri=1; ri < StringGrid1->RowCount; ri++) {  // ri: row index
		member = new TJSONObject();
		for(int ci=0; ci < NUM_ITEM; ci++) {  // ci: column index
			String key = StringGrid1->Cells[ci][0];  // 0: 1行目(title)を取る
			String value = StringGrid1->Cells[ci][ri];
			if (value.Length() == 0) { // 空データ
				break;
			}
			member->AddPair(key, value);
		}
		if (member->Size() > 0) {
			jary->AddElement(member);
		}
	}

	// 2. ファイル保存
	std::unique_ptr<TStringList> sl(new TStringList);
	sl->Add( json->ToString() );
	sl->SaveToFile(kSaveFile);

	// 3. 手仕舞い
	//member->Free(); // Error: 無効なポインタ操作
	//jary->Free(); // Error: 無効なポインタ操作
	json->Free();

	ShowMessage(L"Saved to [" + kSaveFile + L"]");
}
//---------------------------------------------------------------------------
```

### 実行例

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/11d01793-f541-bac2-5ad2-fb0a1a02ca4a.png)

結果ファイル:

```out180419.JSON
{"member":[{"name":"7of9","age":"120","type":"borg"},{"name":"Janeway","age":"40","type":"human"},{"name":"Odo","age":"250","type":"shapeShifter"}]}
```

下記は、[JSON Pretty Linter Ver3](https://lab.syncer.jp/Tool/JSON-Viewer/)にて整形後
関連:[onlineTool > JSON > JSON整形 > JSON-Viewer (JSON Pretty Linter Ver3)](https://qiita.com/7of9/items/5269576a9d69326267e1)

```txt:
{
    "member": [
        {
            "name": "7of9",
            "age": "120",
            "type": "borg"
        },
        {
            "name": "Janeway",
            "age": "40",
            "type": "human"
        },
        {
            "name": "Odo",
            "age": "250",
            "type": "shapeShifter"
        }
    ]
}
```

### ひっかかり

memberとjaryのFree()で「無効なポインタ操作」となる。


### link

[C++ Builder + JSON関連](https://qiita.com/search?utf8=%E2%9C%93&sort=created&q=user%3A7of9+tag%3AJSON+tag%3Acppbuilder)