0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

C++ Builder 10.2 Tokyo > JSON > JSONファイルを読込み、一部のキーの値を変更して、ファイル保存 | 事象: Freeした場合、ToString()時にAccess Violation

Last updated at Posted at 2019-05-07
動作環境
RAD Studio 10.2 Tokyo Update 3

概要

  • JSONファイルを読込む
  • 指定のキーを探す (部分文字列)
  • 値を変更する
  • ファイル出力

参考

実装

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

Free()でなくdeleteを使う。

以前にも教えていただいたいたが、忘れていたこと。

pairObj->JsonValue->Free();

ではなく

delete pairObj->JsonValue;

newとdeleteの組合せ。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?