1

I have a code that changes a value of a determinated pair in a existent JSON file and works perfectly. Now i need add one object and one pair to this file, using great part this same code. So how do this?

Thank you.

uses
 System.Json, ShFolder, System.IOUtils;

...

function GetSpecialFolderPath(folder : integer) : string;
 const
   SHGFP_TYPE_CURRENT = 0;
 var
   path: array [0..MAX_PATH] of char;
 begin
   if SUCCEEDED(SHGetFolderPath(0,folder,0,SHGFP_TYPE_CURRENT,@path[0])) then
     Result := path
   else
     Result := '';
 end;

procedure ChangeChromeSetting(const ATarget, Avalue: string);
var
  specialfolder: integer;
  caminhochrome: String;
  JSONObj, Obj: TJSONObject;
  JSONPair: TJSONPair;
  OldValue: string;
begin
  specialFolder := CSIDL_LOCAL_APPDATA;
  caminhochrome := GetSpecialFolderPath(specialFolder);
  caminhochrome := caminhochrome + '\Google\Chrome\User Data\Local State';

 if fileexists(caminhochrome) then
  begin
    Obj := TJSONObject.Create;
    JSONObj := TJSONObject.ParseJSONValue(TFile.ReadAllText(caminhochrome)) as TJSONObject;
    if not Assigned(JSONObj) then raise Exception.Create('Cannot read file: ' + caminhochrome);
    try
      OldValue := JSONObj.GetValue<string>(ATarget);
      if not SameText(OldValue, Avalue) then
      begin
        JSONPair := JSONObj.Get(ATarget);
        JSONPair.JsonValue.Free;
        JSONPair.JsonValue := TJSONString.Create(Avalue);
        ///////////////////////////////////////////////////
        Obj.AddPair('enabled', TJSONBool.Create(false)); // Trying add pair
        JSONObj.AddPair('hardware_acceleration_mode', Obj);  // Trying add object
        //////////////////////////////////////////////////
        TFile.WriteAllText(caminhochrome, JSONObj.ToJSON); // Don't add object and pair
      end;
    finally
      JSONObj.Free;
    end;
  end;
end;


procedure TForm1.Button1Click(Sender: TObject);
begin
  ChangeChromeSetting('hardware_acceleration_mode_previous', 'false');
end;

This is result that i'm waiting

"hardware_acceleration_mode":{"enabled":false}

1 Answers1

1

Your code is somewhat confusing since you pass in some of the names as arguments, but then hard code others inside the function. Abstracting functionality is good practise but before you can abstract you really need to ensure the code works correctly. I'm going to show code that does not attempt to be abstract. Once you are satisfied it behaves as you need, then feel free to abstract away.

This code does what I believe is your intent:

var
  root: TJSONObject;
  value: TJSONObject;
  prev: string;
begin
  root := TJSONObject.ParseJSONValue(TFile.ReadAllText(FileName)) as TJSONObject;
  try
    prev := root.GetValue<string>('hardware_acceleration_mode_previous');
    if not SameText(prev, 'false') then
    begin
      // remove existing value, if it exists
      root.RemovePair('hardware_acceleration_mode').Free;

      // create a new object, and initialise it
      value := TJSONObject.Create;
      value.AddPair('enabled', 'false');

      // add the object at the root level
      root.AddPair('hardware_acceleration_mode', value);

      // save to file
      TFile.WriteAllText(FileName, root.ToJSON);
    end;
  finally
    root.Free;
  end;
end;

Note that I have ensured that there are no memory leaks. I've used RemovePair to make sure that if there is an existing value named hardware_acceleration_mode it is first removed.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490