動作環境
RAD Studio 10.2 Tokyo Update 3
概要
- JSONファイルを読込む
- 指定のキーを探す (部分文字列)
- 値を変更する
- ファイル出力
参考
-
Delphi XE7: How to change a JSON value using System.JSON (versus SuperObject)
- Delphiでの実装例
- 値変更には
JoX.JsonValue.Free;
JoX.JsonValue := TJSONNumber.Create(123);
実装
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;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
String srcFileName = L"test.json"; // 読込元
String dstFileName = L"out.json"; // 保存先
String targetKeySubString = L"hogehoge"; //
String targetValue = "9";
// 1. JSON文字列の読込み
std::unique_ptr<TStringList> slread(new TStringList);
slread->LoadFromFile(srcFileName);
// 2. JSON文字列を読みながら、対象となる文字列を含むキーの値は置換する
TJSONObject *jsonObj;
String jsonKey, jsonValue;
TJSONPair *pairObj;
std::unique_ptr<TStringList> slwrite(new TStringList);
for(int li=0; li < slread->Count; li++) { // file line index
String jsonText = slread->Strings[li];
// フォルダに使われる"\"の扱いによるエラー対応のため
jsonText = StringReplace(jsonText, L"\\", L"\\\\", TReplaceFlags()<<rfReplaceAll);
//
jsonObj = dynamic_cast<TJSONObject*>(TJSONObject::ParseJSONValue(jsonText));
for(int pi=0; pi < jsonObj->Size(); pi++) { // pair index
pairObj = jsonObj->Get(pi);
jsonKey = pairObj->JsonString->Value();
jsonValue = pairObj->JsonValue->Value();
if (jsonKey.Pos(targetKeySubString) == 0) {
continue;
}
// replace value
// (ref: https://stackoverflow.com/questions/33426576/delphi-xe7-how-to-change-a-json-value-using-system-json-versus-superobject)
//
//pairObj->JsonValue->Free(); // これがあることでToString()時にaccess violationとなるためコメントアウト
pairObj->JsonValue = new TJSONString(targetValue);
// debug
//ShowMessage(jsonKey + ":" + jsonValue);
}
slwrite->Add(jsonObj->ToString());
}
jsonObj->Free();
// 3. ファイル出力
slwrite->SaveToFile(dstFileName);
ShowMessage(L"Done");
}
//---------------------------------------------------------------------------
実行例
test.json
{"1_hogehoge":"3", "2_fugafuga":"1","3_hogehoge":"4", "4_fugafuga":"1", "5_hogehoge":"5", "6_fugafuga":"9"}
out.json
{"1_hogehoge":"9","2_fugafuga":"1","3_hogehoge":"9","4_fugafuga":"1","5_hogehoge":"9","6_fugafuga":"9"}
ひっかかり
//pairObj->JsonValue->Free(); // これがあることでToString()時にaccess violationとなるためコメントアウト
Delphi実装例では上記のFree処理をしているが、C++ BuilderでこれをするとToString()時にAccess Violationとなる。
この実装だとメモリリークするかどうか。
未調査。
Stackoverflow
Free()でなくdelete
-
C++ Builder 10.2 Tokyo > JSON > replace JSONvalue causes “access violation” with JsonValue->Free()
のコメントにて教えていただいたこと
Free()でなくdeleteを使う。
以前にも教えていただいたいたが、忘れていたこと。
pairObj->JsonValue->Free();
ではなく
delete pairObj->JsonValue;
newとdeleteの組合せ。