PizzaProgram 9 Posted November 11, 2022 Hi, I'm trying this function the first time and it would be really great, if it would find the string I'm looking for. Here is my code: procedure TFrm_Ntak.gmb_jsonTesztClick(Sender: TObject); var o : ISuperObject; function stat_search(what: string): string; var JsonSearch : TSuperObjectIter; begin Result := ''; if ObjectFindFirst(o, JsonSearch) then begin repeat if JsonSearch.key = what then begin Result := JsonSearch.val.AsString; Break; end; until not ObjectFindNext(JsonSearch); end; ObjectFindClose( JsonSearch ); end; begin o := SO('{"messageAnswers":[{"id":"fe134b3e-...","successfullMsgs":[{"type":"DAILYCLOSING","rmsID":"fe134b3e-..."}],"status":"SUCCESS"}]}'); ShowMessage( stat_search('status') ); end; Instead of showing : SUCCESS it gives back no result. I can see, that the trouble is caused by the ARRAY, but I simply don't get it, why an "universal search" function can not handle that? So what can I do? I don't know the EXACT form of the json it needs to digest, there can be multiple embedded arrays, or who knows what ... but I need to search for this specific value. Tried to search on stackoverflow + in ICS samples too, no success. Thanks for any help ! 😉 Share this post Link to post
Joseph MItzen 251 Posted November 12, 2022 There is only one key in the top level of the JSON string, "messageAnswers". Hence, iterating over the keys doesn't find "status". If you don't know what you're looking for, you're going to have to do a recursive search throughout the entire structure. Share this post Link to post
PizzaProgram 9 Posted November 12, 2022 (edited) 5 hours ago, Joseph MItzen said: you're going to have to do a recursive search Yes, that's what I wrote too: I know that. To rephrase my question: - Is there no "ready to use" function for that? > if not, WHY ? - Nobody has a finished version? Nobody ever needed such a thing? I can not imagine that! Edited November 12, 2022 by PizzaProgram Share this post Link to post
FPiette 383 Posted November 12, 2022 3 hours ago, PizzaProgram said: > if not, WHY ? Ask the developer! Before asking, read the SuperObject documentation. Share this post Link to post
Joseph MItzen 251 Posted November 12, 2022 7 hours ago, PizzaProgram said: - Nobody has a finished version? Nobody ever needed such a thing? I can not imagine that! When you're parsing JSON, you should have some idea of what it is you're parsing. This SuperObject library is more of a low-level parsing library rather than a very high level one. Share this post Link to post
Joseph MItzen 251 Posted November 12, 2022 4 hours ago, FPiette said: Ask the developer! Before asking, read the SuperObject documentation. To be fair, that's precious little documentation. It's more like a few examples. I haven't used this library before and when checking I found that even the source code wasn't documented at all. 😞 Share this post Link to post
Joseph MItzen 251 Posted November 12, 2022 7 hours ago, PizzaProgram said: - Nobody has a finished version? Nobody ever needed such a thing? I can not imagine that! I know how to write a function that does this IF one can tell what the type is of a parsed element. But from the minimal "documentation" I see that the user can typecast an element but I don't see a way to check if something is an object or array. If there's no ability to do that, then I'm not sure if one can do this type of search with SuperObject... well, maybe with some ugly exception-handling.... I'll have to test this out later today. Share this post Link to post
FPiette 383 Posted November 13, 2022 13 hours ago, Joseph MItzen said: I don't see a way to check if something is an object or array Use one of the functions: function ObjectIsType(const obj: ISuperObject; typ: TSuperType): boolean; function ObjectGetType(const obj: ISuperObject): TSuperType; 1 Share this post Link to post
Angus Robertson 574 Posted November 13, 2022 If you build the OverbyteIcsHttpRestTst sample application and access your JSON URL, you'll see the sample parses the JSON into a ListView, you can click on an object and it will expand that into another window, mostly done in the DisplayJson procedure using SuperObject DataType. Angus 1 Share this post Link to post
PizzaProgram 9 Posted November 13, 2022 (edited) Sorry for the late response, I've already wrote it myself. Although it would be great to put it directly into: unit OverbyteIcsSuperObject; Should be changed to an universal one, not just "string". The result should be a Boolean. function SearchInAll(inWhat: ISuperObject; const findThis : string): string; // returns '' if not found var JsonSearch : TSuperObjectIter; i : integer; begin Result := ''; if inWhat = nil then Exit; if ObjectFindFirst(inWhat, JsonSearch) then begin repeat if JsonSearch.key = findThis then Result := JsonSearch.val.AsString else if JsonSearch.val.DataType = stObject then Result := js_keres( JsonSearch.val, findThis ) else if JsonSearch.val.DataType = stArray then begin for i := 0 to JsonSearch.val.AsArray.Length -1 do begin Result := js_keres( JsonSearch.val.AsArray.O[i], findThis ); if Result <> '' then Break; end; end; if Result <> '' then Break; until not ObjectFindNext(JsonSearch); end; ObjectFindClose( JsonSearch ); end; Edited November 13, 2022 by PizzaProgram Share this post Link to post
PizzaProgram 9 Posted November 13, 2022 2 hours ago, FPiette said: js_keres A leftover from half-translation. Fixed. Share this post Link to post
FPiette 383 Posted November 13, 2022 47 minutes ago, PizzaProgram said: A leftover from half-translation. Fixed. Please also fix your message. You can edit it. Share this post Link to post
PizzaProgram 9 Posted November 15, 2022 On 11/13/2022 at 8:54 PM, FPiette said: Please also fix your message. Sorry, but which message? Did I spell something wrong? My English is not perfect. Share this post Link to post
FPiette 383 Posted November 15, 2022 27 minutes ago, PizzaProgram said: Sorry, but which message? Did I spell something wrong? My English is not perfect. I mean the code you posted and which contains unknown function js_keres. Share this post Link to post
PizzaProgram 9 Posted November 15, 2022 Hmmm... That's strange! I've replaced all occurrences, wrote: "fixed" on Sunday. Now I see: the code is reverted back, all js_keres naming are back! Maybe some browser-cashing problem. Restarted Firefox. I'm fixing again... Share this post Link to post
PizzaProgram 9 Posted November 15, 2022 No, can not EDIT. That function is Disabled. Maybe that was the problem before >> it showed the Edit button on that day, but did not really allow it. Here is it again: function SearchInAll(inWhat: ISuperObject; const findThis : string): string; // returns '' if not found var JsonSearch : TSuperObjectIter; i : integer; begin Result := ''; if inWhat = nil then Exit; if ObjectFindFirst(inWhat, JsonSearch) then begin repeat if JsonSearch.key = findThis then Result := JsonSearch.val.AsString else if JsonSearch.val.DataType = stObject then Result := SearchInAll( JsonSearch.val, findThis ) else if JsonSearch.val.DataType = stArray then begin for i := 0 to JsonSearch.val.AsArray.Length -1 do begin Result := SearchInAll( JsonSearch.val.AsArray.O[i], findThis ); if Result <> '' then Break; end; end; if Result <> '' then Break; until not ObjectFindNext(JsonSearch); end; ObjectFindClose( JsonSearch ); end; 1 Share this post Link to post
PizzaProgram 9 Posted November 15, 2022 PS: Thanks for notifying me, and your patients ! 😉 1 Share this post Link to post
Angus Robertson 574 Posted November 15, 2022 Thanks for the code, added to my local copy, will be in SVN later this week. Angus 1 Share this post Link to post
PizzaProgram 9 Posted November 15, 2022 (edited) On 11/13/2022 at 5:27 PM, PizzaProgram said: Should be changed to an universal one, not just "string". The result should be a Boolean. Can you maybe rewrite it, so it may serve every kind of value? I've never done such thing, so can not help. Something with VarArray ... or like: function SearchInAll(const inWhat: ISuperObject; findThisarray[1..1] of const; var foundValue: TSuperValue): Boolean; Edit: added "foundValue" for adding back the Result, if Boolean = True; Edited November 16, 2022 by PizzaProgram Share this post Link to post
PizzaProgram 9 Posted November 21, 2022 I was thinking how to enhance the practical usage of this ISuperObject component, because it is great, but lack of "easy-to-use" methods. So why not enhance the original methods a bit too, to search in Arrays too ? function ObjectFindFirst(const obj: ISuperObject; var F: TSuperObjectIter; const inArrayToo: Boolean = False): boolean; ... function ObjectFindNext(var F: TSuperObjectIter; const inArraysToo: Boolean = False): boolean; At the FindFirst it would be necessary, because it is possible that the whole JSON is an array. {[{..},{..}]} I've looked into the iterator code, but sadly I do not understand how this whole FPath[FDepth] := h; thing works. Can not understand the concept and there are no comments in the code. So I can not do it myself. What is your opinion? Can / Would you like to enhance it? Share this post Link to post
Angus Robertson 574 Posted November 21, 2022 Sorry, I don't have the time to enhance your code, unless there is a specific application for it. Nor do I change anything for which there are no tests. Angus Share this post Link to post
PizzaProgram 9 Posted November 21, 2022 No problem! I'll see what I can do, and copy the end result here. 😉 Share this post Link to post