Norm Posted July 11 Share Posted July 11 This post explains how to parse a master/detail JSON object in Delphi for those interested. It is an addendum to a post I added to the following thread about REST API: http://forums.unigui.com/index.php?/topic/23222-using-unigui-rest-full-server/#comment-136637 I use here as an example an invoice object in JSON format received via an http POST request. The procedure below parses the the JSON object and stores the invoice field values in a Stringlist for further processing Assuming the object we have received looks like this (1 invoice header and 3 invoice details): // {"invNo":"0001234", "invDate":"2023-06-21","customer":"Robert Smith", "invAmt":271.50, // "invDetails" :[{"seqNo":1, "productCode":"SPRINGS","description":"Galv 2.0m Tensile", "qty":2, "price":120.50}, // {"seqNo":2, "productCode":"LUB","description":"2cm Light Grease", "qty":1, "price":20.50}, // {"seqNo":3, "productCode":"FREIGHT","description":"Freiht Cost", "qty":1, "price":10.00}] // } //Some JSON Helper functions we'll use (Delphi unit required : System.JSON) function getJsonCurrency(wObj: TJSONObject; wItem: String): Currency; var aObjItem : TJSONString; begin aObjItem := wObj.Get(wItem).JsonValue as TJSONString; Result := StrToFloat(aObjItem.Value); end; function getJsonDate(wObj: TJSONObject; wItem: String; fmt : TFormatSettings): Currency; var aObjItem : TJSONString; aValue : String; begin aObjItem := wObj.Get(wItem).JsonValue as TJSONString; aValue := aObjItem.Value; Result := StrToDate(aValue, fmt); end; function getJsonInteger(wObj: TJSONObject; wItem: String): Integer; var aObjItem : TJSONString; begin aObjItem := wObj.Get(wItem).JsonValue as TJSONString; Result := StrToInt(aObjItem.Value); end; function getJsonString(wObj: TJSONObject; wItem: String): String; var aObjItem : TJSONString; begin aObjItem := wObj.Get(wItem).JsonValue as TJSONString; Result := aObjItem.Value; end; //-- //Parsing the object procedure ProcessJSONInvoice(wJSONInvoice: String); type //Invoice Header Structure TInvoiceHeader = Record InvNo : String; Customer : String; InvDate : TDateTime; InvAmt : Currency; end; //Invoice Detail Structure TInvoiceDetail = Record LineSeq : Integer; ItemCode : String; Description : String; Qty : Currency; Price : Currency; end; var aJSONObj : TJSONObject; aDetailsArray : TJSONArray; InvoiceHeader : TInvoiceHeader; InvoiceDetail : TInvoiceDetail; aInvoiceData, aDataItems : TStringList; i : Integer; dateFmt : TFormatSettings; begin aInvoiceData := TStringList.Create; aDataItems := TStringList.Create; aJSONObj := TJSONObject.ParseJSONValue(wJSONInvoice) as TJSONObject; try //Our Date Format dateFmt := TFormatSettings.Create(LOCALE_USER_DEFAULT); dateFmt.ShortDateFormat := 'yyyy/mm/dd'; dateFmt.DateSeparator := '-'; //Extract Invoice Header with InvoiceHeader do begin InvNo := getJsonString(aJSONObj, 'invNo'); InvDate := getJsonDate(aJSONObj, 'invDate', dateFmt); Customer := getJsonString(aJSONObj, 'customer'); InvAmt := getJsonCurrency(aJSONObj, 'invAmt'); //Add to StringList aDataItems.Clear; aDataItems.Add('Header'); aDataItems.Add(InvNo); aDataItems.Add(DateToStr(InvDate)); aDataItems.Add(Customer); aDataItems.Add(FloatToStr(InvAmt)); aInvoiceData.Add(aDataItems.CommaText); end; //Extract Invoice Details aDetailsArray := aJSONObj.Get('invDetails').JsonValue as TJSONArray; for i := 0 to aDetailsArray.Count - 1 do begin aJSONObj := aDetailsArray.Items[i] as TJSONObject; with InvoiceDetail do begin LineSeq := getJsonInteger(aJSONObj, 'seqNo');; ItemCode := getJsonString(aJSONObj, 'productCode'); Description := getJsonString(aJSONObj, 'description');; Qty := getJsonCurrency(aJSONObj, 'qty'); Price := getJsonCurrency(aJSONObj, 'price');; //Add Invoice Details to StringList aDataItems.Clear; aDataItems.Add('Detail'); aDataItems.Add(IntToStr(LineSeq)); aDataItems.Add(ItemCode); aDataItems.Add(Description); aDataItems.Add(FloatToStr(Qty)); aDataItems.Add(FloatToStr(Price)); aInvoiceData.Add(aDataItems.CommaText); end; end; //Forward the stringlist for DB processing; // ProcessInvoice(aInvoiceData); finally aJSONObj.Free; aInvoiceData.Free; aDataItems.Free; end; end; Quote Link to comment Share on other sites More sharing options...
Sherzod Posted July 11 Share Posted July 11 Hello @Norm Thanks. Quote Link to comment Share on other sites More sharing options...
Oliver Morsch Posted July 11 Share Posted July 11 Why not just create Delphi classes TInvDetail = class public seqNo: Integer; productCode: string; description: string; qty: Integer; price: Double; end; TInvoice = class public invNo: string; invDate: TDateTime; customer: string; invAmt: Double; invDetails: TArray<TInvDetail>; end; And then use var Invoice: TInvoice; begin Invoice := TJson.JsonToObject<TInvoice>(...) ??? Quote Link to comment Share on other sites More sharing options...
Norm Posted July 11 Author Share Posted July 11 My intention was explain how to pass a JSON object in Delphi with the simplest code possible because someone asked me to, not to provide an OO and business logic tutorial. I thought the use of primitive Records instead of classes and the verbose transfer of the data via StringLists would have made that obvious. I'm sure nobody writes code like that. Quote Link to comment Share on other sites More sharing options...
Oliver Morsch Posted July 11 Share Posted July 11 28 minutes ago, Norm said: with the simplest code possible I find my solution easier Quote Link to comment Share on other sites More sharing options...
Norm Posted July 11 Author Share Posted July 11 Good. I'm happy for you. Quote Link to comment Share on other sites More sharing options...
Fred Montier Posted September 14 Share Posted September 14 (edited) Best solution: 1- https://jsontodelphi.com/ Paste your JSon example and it will generate all code and units to use it in your Delphi project in the best way available. (It's a "Marlon Nardin"'s project. You can get in touch with him at this very forum). 2- In your Delphi Project declare the units downloaded from the website and just use as a regular class. 3- There is no better solution than this one to Delphi/JSon, regarding accessing/importing JSon data to your project. It should be native to RAD IDE tool's case. 4- Se Dataset Serializer at GitHub (https://github.com/viniciussanchez/dataset-serialize-adapter-restrequest4delphi) that provide more powerful features and manipulating JSon as a regular Table. 5- Learn to use JS function JSON.stringify() and ajaxRequest, in all of its mess with uniURLFrame, and HTMLFrame. That's all you need to move data between webbrowser, forms and Delphi (unigui) tables and DB logic. I'm working on a new book all about those topics and more. Edited September 28 by Fred Montier typos 2 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.