動作環境
RAD Studio 10.2 Tokyo Update 3
処理概要
- JSONオブジェクトのValueを置換したい
- 用途: 変換元と変換先の文字列が渡されたとき、それに基づきJSONの中身を書換える
方針
- ToString()した文字列に対して置換をする
- その結果をJSONオブジェクトとして戻す
実装
Unit1.h
//---------------------------------------------------------------------------
# ifndef Unit1H
# define Unit1H
//---------------------------------------------------------------------------
# include <System.Classes.hpp>
# include <Vcl.Controls.hpp>
# include <Vcl.StdCtrls.hpp>
# include <Vcl.Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE で管理されるコンポーネント
TButton *Button1;
TMemo *Memo1;
void __fastcall Button1Click(TObject *Sender);
void __fastcall FormCreate(TObject *Sender);
private: // ユーザー宣言
TJSONObject * __fastcall JSON_replaceStrings(TJSONObject *srcPtr, String fromStr, String toStr);
public: // ユーザー宣言
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
# endif
Unit1.cpp
//---------------------------------------------------------------------------
# include <vcl.h>
# pragma hdrstop
# include <DBXJSON.hpp>
# include <memory>
# 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)
{
TJSONObject *asrc, *adst;
asrc = new TJSONObject();
asrc->AddPair(L"name", L"John Smith");
asrc->AddPair(L"age", L"33");
asrc->AddPair(L"place", L"Sydney");
Memo1->Lines->Add(asrc->ToString());
String fromstr = "John Smith,33";
String tostr = "7of9,79";
adst = JSON_replaceStrings(asrc, fromstr, tostr);
if (adst != NULL) {
Memo1->Lines->Add(adst->ToString());
}
delete asrc;
delete adst;
}
TJSONObject * __fastcall TForm1::JSON_replaceStrings(TJSONObject *srcPtr, String fromStr, String toStr)
{
// 1. parse csv string
std::unique_ptr<TStringList> fromSL(new TStringList);
fromSL->StrictDelimiter = true;
fromSL->DelimitedText = ',';
fromSL->DelimitedText = fromStr;
std::unique_ptr<TStringList> toSL(new TStringList);
toSL->StrictDelimiter = true;
toSL->DelimitedText = ',';
toSL->DelimitedText = toStr;
if (fromSL->Count != toSL->Count) {
return NULL; // error
}
// 2. replace values
String replaced = srcPtr->ToString();
for(int idx=0; idx<fromSL->Count; idx++) {
String afrom = fromSL->Strings[idx];
String ato = toSL->Strings[idx];
replaced = StringReplace(replaced, afrom, ato, TReplaceFlags()<<rfReplaceAll);
}
return dynamic_cast<TJSONObject*>(TJSONObject::ParseJSONValue(replaced));
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
Memo1->Lines->Clear();
}
//---------------------------------------------------------------------------
実行例
問題点
意図しない置換 (連鎖的な失敗)
(1,2,3,4,5)
のようなValueを持つ5つのKeyを持つJSONオブジェクトがあるとする。
(2,3,4,5,6)
に置換するとき、StringReplace()を逐次実施すると'(6,6,6,6,6)`になってしまう場合がある。
(1,2,3,4,5)
(2,2,3,4,5)
(3,3,3,4,5)
(4,4,4,4,5)
(5,5,5,5,5)
(6,6,6,6,6)