I'm trying to get JSON working in C++Builder. I have been looking at code for Delphi on making a JSON file, and they all seem to create the Doc and Data parts of the JSON file/string, but only free the Doc.
For example:
void __fastcall TMainForm::Panel1Click(TObject* Sender)
{
std::unique_ptr<TJSONObject> jsonDoc { new TJSONObject() };
TJSONObject* jsonData = new TJSONObject();
jsonDoc->AddPair("cmd", rdsNowPlaying);
jsonDoc->AddPair("station", "WBCB_FM");
jsonDoc->AddPair("data", jsonData);
jsonData->AddPair("testNull", new TJSONNull() );
jsonData->AddPair("testTrue", new TJSONBool(true) );
jsonData->AddPair("testFalse", new TJSONBool(false) );
Memo1->Lines->Text = jsonDoc->Format(3);
}
Does jsonDoc->AddPair("data", jsonData);
give "ownership" of jsonData
to jsonDoc
? So when jsonDoc
is freed, jsonData
is freed too?
Does jsonData->AddPair("testTrue", new TJSONBool(true) );
assign ownership of the TJSONBool
to jsonData
and it is freed when jsonData
is freed?
Triggering the OnClick
event displays correctly, but it's another "How do I free (delete) the memory" question? Or does std::unique_ptr
and the TJSONObject
take care of itself?
p.s. rdsNowPlaying
is an enum
declared in the header.
By default, the top-level JSON value owns all of the child objects in its hierarchy. So yes, freeing jsonDoc
will free everything that is inside of it.
You can manually set a JSON value's Owned
property to false
if you want to take ownership of something yourself.
UPDATE:
That being said, in your particular code example, AddPair()
has the potential to throw an exception, and if that happens while you are calling new
on one of its parameters, you will leak that new
'ed object before jsonDoc
can take ownership of it. If you are going to new
an object directly, make sure you delete
it if you are not able to transfer ownership of it. unique_ptr
can help you with that, eg:
void __fastcall TMainForm::Panel1Click(TObject* Sender)
{
std::unique_ptr<TJSONObject> jsonDoc = std::make_unique<TJSONObject>();
std::unique_ptr<TJSONObject> jsonData = std::make_unique<TJSONObject>();
...
jsonDoc->AddPair(_D("data"), jsonData.get());
jsonData.release();
std::unique_ptr<TJSONNull> jsonNull = std::make_unique<TJSONNull>();
jsonData->AddPair(_D("testNull"), jsonNull.get());
jsonNull.release();
std::unique_ptr<TJSONTrue> jsonTrue = std::make_unique<TJSONTrue>();
jsonData->AddPair(_D("testTrue"), jsonTrue.get());
jsonTrue.release();
std::unique_ptr<TJSONFalse> jsonFalse = std::make_unique<TJSONFalse>();
jsonData->AddPair(_D("testFalse"), jsonFalse.get());
jsonFalse.release();
Memo1->Lines->Text = jsonDoc->Format(3);
}
In the case of your booleans (and integers and strings), you can use the AddPair()
overloads that create JSON objects for you (unfortunately, there is no method that will create a TJSONNull
for you), eg:
void __fastcall TMainForm::Panel1Click(TObject* Sender)
{
std::unique_ptr<TJSONObject> jsonDoc = std::make_unique<TJSONObject>();
std::unique_ptr<TJSONObject> jsonData = std::make_unique<TJSONObject>();
...
jsonDoc->AddPair(_D("data"), jsonData.get());
jsonData.release();
std::unique_ptr<TJSONNull> jsonNull = std::make_unique<TJSONNull>();
jsonData->AddPair(_D("testNull"), jsonNull.get());
jsonNull.release();
jsonData->AddPair(_D("testTrue"), true);
jsonData->AddPair(_D("testFalse"), false);
Memo1->Lines->Text = jsonDoc->Format(3);
}