I work with Inno JSON Config (like in Pascal Script fails to retrieve wide string from a custom DLL) to read a simple JSON file named items.json
:
{
"Item_0":{
"Key_1": "String 1",
"Key_2": "1",
"Key_3": "True"
},
"Item_1":{
"Key_1": "String 2",
"Key_2": "2",
"Key_3": "False"
}
}
Here is my code :
[Files]
Source: "JSONConfig.dll"; DestDir: "{tmp}\src"; Flags: dontcopy;
Source: "json_lists\*"; DestDir: "{tmp}\json_lists"; Flags: dontcopy;
[Code]
var
ItemList: array of WideString;
function JSONQueryString(FileName, Section, Key, Default: WideString;
var Value: WideString; var ValueLength: Integer): Boolean;
external 'JSONQueryString@files:jsonconfig.dll stdcall';
procedure AppendItem(var ItemArray: array of WideString; Item: WideString);
begin
SetLength(ItemArray, GetArrayLength(ItemArray) + 1);
ItemArray[GetArrayLength(ItemArray) - 1] := Item;
end;
function ParseJson(Filename: WideString; Item: String; Key: String; var ItemArray: array of WideString): Boolean;
var
StrValue: WideString;
StrLength: Integer;
ItemNumber: Integer;
Path: WideString;
begin
SetLength(StrValue, 32);
StrLength := Length(StrValue);
result := False;
Path := ExpandConstant('{tmp}'+ '\json_lists\' + Filename);
ItemNumber := 0;
while JSONQueryString(Path, ExpandConstant(Item + '_' + IntToStr(ItemNumber)), Key, 'Default', StrValue, StrLength) do
begin
ItemNumber := ItemNumber + 1;
AppendItem(ItemArray, StrValue);
result := True;
end;
end;
function NextButtonClick(CurPageID: Integer): Boolean;
var
I: Integer;
PathForNextFile: WideString;
begin
if CurPageID = wpWelcome then
begin
if GetArrayLength(ItemList) = 0 then begin
ExtractTemporaryFiles('{tmp}\json_lists\*');
if ParseJson('items.json','Item', 'Key_1', ItemList) then begin
for I := 0 to GetArrayLength(ItemList) - 1 do begin
PathForNextFile := ItemList[I] + '.json';
Log(PathForNextFile); //**
end;
end else begin
Log('Error while parsing')
end;
end;
end;
result := True;
end;
I have two issues at //**
in the code (line Log(PathForNextFile);
):
PathForNextFile
with the suffix '.json' to parse another file.I don't know why this happens, any help is welcome!
Ideally I'd like to deal only with String
and not WideString
, so should I code a PowerShell script which, when called in Inno Setup, returns the right info as a String
, if it is possible?
I tried to use koldev's JsonParser Library but I couldn't figure out how it worked, even with How to parse a JSON string in Inno Setup? So yet again any help is welcome!
Even the original code from Inno Setup: Working with JSON returns the value truncated. The comment there by @yuval from 2015 (!) says it:
Also JSONQueryString never retrieves the last character
I recommend you to use JsonParser library.
The following is an equivalent of your code implemented using JsonParser library (and my convenience functions from How to parse a JSON string in Inno Setup?):
function ParseJsonFile(
Filename: string; Item: string; Key: string; var ItemArray: array of string):
Boolean;
var
JsonLines: TStringList;
JsonParser: TJsonParser;
ItemNumber: Integer;
JsonRoot, ItemObject: TJsonObject;
StrValue: TJsonString; // = WideString = string
ItemKey: string;
begin
JsonLines := TStringList.Create;
JsonLines.LoadFromFile(Filename);
Result := False;
if ParseJsonAndLogErrors(JsonParser, JsonLines.Text) then
begin
JsonRoot := GetJsonRoot(JsonParser.Output);
ItemNumber := 0;
while True do
begin
ItemKey := Format('%s_%d', [Item, ItemNumber]);
if FindJsonObject(JsonParser.Output, JsonRoot, ItemKey, ItemObject) and
FindJsonString(JsonParser.Output, ItemObject, Key, StrValue) then
begin
Inc(ItemNumber);
SetLength(ItemArray, GetArrayLength(ItemArray) + 1);
ItemArray[GetArrayLength(ItemArray) - 1] := StrValue;
Result := True;
end
else Break;
end;
end;
ClearJsonParser(JsonParser);
end;