问题
I need to load a JSON file, change a value and then write it back to disk.
This is easy using SuperObject, but how do I do the same thing using the System.JSON unit?
const
PathToX = 'AllCategories.Category[0].subCategory[0].products[0].views.view[0].x';
var
JsonFilename: string;
JO: ISuperObject; // from the SuperObject unit
JV: TJsonValue; // from the System.Json unit
begin
JsonFilename := ExtractFilePath(Application.ExeName)+'product.json');
// Using the SuperObject unit:
JO := SO(TFile.ReadAllText(JsonFilename));
WriteLn('The old value of "x" is ', JO[PathToX].AsString);
WriteLn('Changing value of x to "123"');
JO.S[PathToX] := '123'; // Set the value of "x"
WriteLn('The new value of "x" is ', JO[PathToX].AsString);
// Now trying to do the same thing using the System.Json unit:
JV := TJSONObject.ParseJsonValue(TFile.ReadAllText(JsonFilename));
WriteLn('The old value of "x" is ', JV.GetValue<string>(PathToX));
WriteLn('Changing value of x to "123"');
// Question: What code should go here to set the value of "x" using System.JSON ???
WriteLn('The new value of "x" is ', JV.GetValue<string>(PathToX));
There doesn't seem to be a "SetValue" equivalent to the "GetValue" method in System.JSON.
回答1:
TJSONObject
does support a path evaluator similar to SuperObject. So you will not have to manually drill into the JSON value tree one object at a time (though you certainly could if you wanted to).
However, the System.JSON
classes are actually NOT designed for modifying existing data (believe it or not)! They are designed for parsing data, and creating new data. All of the JSON classes that represent simple values (integers, boolean, strings) are read-only. Fortunately, the TJSONPair
class allows a value to be replaced, so you will have to take advantage of that.
Try something like this:
uses
..., System.JSON;
var
JsonFilename: string;
JV: TJSONValue;
JO: TJSONObject;
JoX: Integer;
JoPair: TJSONPair;
begin
JsonFilename := ExtractFilePath(Application.ExeName) + 'product.json';
JV := TJSONObject.ParseJSONValue(TFile.ReadAllText(JsonFilename));
if JV = nil then raise Exception.Create('Cannot parse file: ' + JsonFilename);
try
JO := JV as TJSONObject;
JoX := JO.GetValue<Integer>('AllCategories.Category[0].subCategory[0].products[0].colors.color[0].views.view[0].x');
WriteLn('The old value of "x" is ', JoX);
WriteLn('Changing value of "x" to "123"');
JoPair := JO.GetValue<TJSONObject>('AllCategories.Category[0].subCategory[0].products[0].colors.color[0].views.view[0]').Get('x');
JoPair.JsonValue.Free;
JoPair.JsonValue := TJSONNumber.Create(123);
WriteLn('The new value of "x" is ', JoPair.JsonValue.Value);
SaveAsDialog.FileName := JsonFilename;
if SaveAsDialog.Execute then TFile.WriteAllText(SaveAsDialog.FileName, JO.ToJSON);
finally
JV.Free;
end;
end;
Alternatively:
uses
..., System.JSON;
var
JsonFilename: string;
JV: TJSONValue;
JO: TJSONObject;
JoX: TJSONPair;
begin
JsonFilename := ExtractFilePath(Application.ExeName) + 'product.json';
JV := TJSONObject.ParseJSONValue(TFile.ReadAllText(JsonFilename));
if JV = nil then raise Exception.Create('Cannot parse file: ' + JsonFilename);
try
JO := JV as TJSONObject;
JoX := JO.GetValue<TJSONObject>('AllCategories.Category[0].subCategory[0].products[0].colors.color[0].views.view[0]').Get('x');
WriteLn('The old value of "x" is ', JoX.JsonValue.Value);
WriteLn('Changing value of "x" to "123"');
JoX.JsonValue.Free;
JoX.JsonValue := TJSONNumber.Create(123);
WriteLn('The new value of "x" is ', JoX.JsonValue.Value);
SaveAsDialog.FileName := JsonFilename;
if SaveAsDialog.Execute then TFile.WriteAllText(SaveAsDialog.FileName, JO.ToJSON);
finally
JV.Free;
end;
end;
来源:https://stackoverflow.com/questions/33426576/delphi-xe7-how-to-change-a-json-value-using-system-json-versus-superobject