#1 2016-07-11 17:43:27

ertank
Member
Registered: 2016-03-16
Posts: 163

JsonSerialization question

Hi,

I have below record definitions.

  TStTicket = packed record
    TransactionFlags: UInt32;
    OptionFlags: UInt32;
    ZNo: UInt16;
    FNo: UInt16;
    EJNo: UInt16;
    TotalReceiptAmount: UInt32;
    TotalReceiptTax: UInt32;
    TotalReceiptDiscount: UInt32;
    TotalReceiptIncrement: UInt32;
    CashBackAmount: UInt32;
    TotalReceiptItemCancel: UInt32;
    TotalReceiptPayment: UInt32;
    TotalReceiptReversedPayment: UInt32;
    KasaAvansAmount: UInt32;
    KasaPaymentAmount: UInt32;
    invoiceAmount: UInt32;
    invoiceAmountCurrency: UInt32;
    KatkiPayiAmount: UInt32;
    TaxFreeRefund: UInt32;
    TaxFreeCalculated: UInt32;
    bcdTicketDate: string;  
    bcdTicketTime: string; 
    ticketType: Byte;
    totalNumberOfItems: UInt16;
    numberOfItemsInThis: UInt16;
    totalNumberOfPayments: UInt16;
    numberOfPaymentsInThis: UInt16;
    TckNo: string;
    invoiceNo: string;
    invoiceDate: UInt32;
    invoiceType: Byte;
    totalNumberOfPrinterLines: Integer;
    numberOfPrinterLinesInThis: Integer;
    uniqueId: Array [0..23] of Byte;
    SaleInfo: Array [0..511] of TStSaleinfo;
    stPayment: TStPayment;
    stTaxDetails: Array [0..7] of TStVATDetail;
    stPrinterCopy: Array [0..1023] of TStPrinterDataForOneLine;
  end;

  TStSaleinfo = packed record
    ItemType: Byte;
    ItemPrice: UInt64;
    IncAmount: UInt64;
    DecAmount: UInt64;
    OrigialItemAmount: UInt32; 
    OriginalItemAmountCurrency: UInt16;
    ItemVatRate: UInt16;
    ItemCurrencyType: UInt16;
    ItemVatIndex: Byte;
    ItemCountPrecision: Byte;
    ItemCount: Integer;
    ItemUnitType: Byte;
    DeptIndex: Byte;
    Flag: UInt32;
    Name: string;
    Barcode: string;
  end;

  TStPayment = packed record
    flags: Byte;
    dateOfPayment: UInt32;
    typeOfPayment: UInt32;              // EPaymentTypes
    subtypeOfPayment: Byte;             // EPaymentSubtypes
    orgAmount: UInt32;                  // Exp; Currency Amount
    orgAmountCurrencyCode: UInt16;      // as defined in currecyTable from GIB
    payAmount: UInt32;                  
    payAmountCurrencyCode: UInt16;      
    cashBackAmountInTL: UInt32;         // currency with precision 2
    cashBackAmountInDoviz: UInt32;      // if currency sale, then curency amount
    stBankPayment: TStBankPaymentInfo;  // Keeps all payment info related with bank
  end;

  TStBankPaymentInfo = packed record
    batchNo: UInt32;
    stan: UInt32;
    balance: UInt32;
    bankBkmId: UInt16;
    numberOfdiscount: Byte;
    numberOfbonus: Byte;
    authorizeCode: string;
    transFlag: Array [0..1] of Byte;
    terminalId: string;
    rrn: string;
    merchantId: string;
    bankName: string;
    numberOfInstallments: Byte;
    numberOfsubPayment: Byte;
		numberOferrorMessage: Byte;
    stBankSubPaymentInfo: Array [0..11] of TStBankSubPaymentInfo;
    stCard: TStCardInfo;
    stPaymentErrMessage: TStPaymentErrMessage;
  end;

  TStBankSubPaymentInfo = packed record
    My_type: UInt16; 				// EPaymentSubType
	  amount: UInt32;
	  name: string;
  end;

  TStCardInfo = packed record
    inputType: Byte;
    pan: string;
    holderName: string;
    My_type: string;
    expireDate: string;
  end;

  TStPaymentErrMessage = packed record
    ErrorCode: string;    // bank error code
    ErrorMsg: string;
    AppErrorCode: string; // payment application specific error code
    AppErrorMsg: string;
  end;

  TStVATDetail = packed record
    u32VAT: Integer;                    //**< Total Tax in TL with precition 2 */
    u32Amount: Integer;                 //**< Total Amount in TL with precition 2 */
    u16VATPercentage: UInt16;           //**< Tax rate, it is 1800 for %18 */
  end;

  TStPrinterDataForOneLine = packed record
    Flag: UInt32;
    lineLen: Byte;
    line: string;
  end;

I am using below code to serialize this records into json:

var
  StTicket: TStTicket;
  JsonString: RawUTF8;
begin
  JsonString := RecordSaveJSON(StTicket, TypeInfo(TStTicket));
end;

I have quite a long json string. It's all fine but serialization of "StTaxDetails" defined in TStTicket. What I am having as a serialized json is something like below (beginning and end is cut for making it more readable):

.....":""}}},"stTaxDetails":"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","stPrinterCopy":[{".....

What I was expecting is something like:

.....":""}}},"stTaxDetails":[{"u32VAT":0,"u32Amount":0,"u16VATPercentage":0},{"u32VAT":0,"u32Amount":0,"u16VATPercentage":0},{"u32VAT":0,"u32Amount":0,"u16VATPercentage":0},{"u32VAT":0,"u32Amount":0,"u16VATPercentage":0},{"u32VAT":0,"u32Amount":0,"u16VATPercentage":0},{"u32VAT":0,"u32Amount":0,"u16VATPercentage":0},{"u32VAT":0,"u32Amount":0,"u16VATPercentage":0},{"u32VAT":0,"u32Amount":0,"u16VATPercentage":0}],"stPrinterCopy":[{".....

I am simply stuck at this point. Is it me doing some wrong record declaration(s) here?

Any help is appreciated.

Thanks.

Offline

#2 2016-07-11 20:55:07

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,240
Website

Re: JsonSerialization question

Which version of Delphi are you using?
You need the extended rtti..
Or you need to define the record serialization using text as stated by the doc.

Offline

#3 2016-07-12 03:33:47

Chaa
Member
Registered: 2011-03-26
Posts: 245

Re: JsonSerialization question

Offline

#4 2016-07-12 04:57:48

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,240
Website

Re: JsonSerialization question

@chaa This is not what I meant.
The framework does it without use of this unit.

Offline

#5 2016-07-12 08:30:08

Chaa
Member
Registered: 2011-03-26
Posts: 245

Re: JsonSerialization question

RTTI will be generated only if a record contains a "managed type" like dynamic arrays, strings or interfaces.

For that record:

TStVATDetail = packed record
    u32VAT: Integer;
    u32Amount: Integer;
    u16VATPercentage: UInt16;
  end;

compiler will not create RTTI info.

But if you use code like this:

type
  TStVATDetails = array[0..7] of TStVATDetail;

then RTTI will be generated.

Offline

#6 2016-07-12 08:51:22

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,240
Website

Re: JsonSerialization question

@Chaa
AFAIR since Delphi 2010, there is extended RTTI information for all records, including the one without any managed type within.

In all cases, the safest is to define the record layout using text, so that it would be compatible with all versions of Delphi compiler, and also with FPC.
See http://synopse.info/files/html/Synopse% … ml#TITL_51

Offline

#7 2016-07-12 13:58:15

ertank
Member
Registered: 2016-03-16
Posts: 163

Re: JsonSerialization question

Sorry, I couldn't be on the Internet before.

I am using Delphi 10.

Is there an option to "extend" rtti for Delphi 10? I do not have deep knowledge about rtti, and do not know if there is such an option/parameter etc.

This json, for me, needs to be generated as Integer type like

"u32VAT":0

and if I am to define these record as string variables, I believe json generated will be like

"u32VAT":"0"

As I am exchanging information with another software, this will be a problem for me. I already used "TTextWriter.RegisterCustomJSONSerializerFromText()" function in my application. However, it was a direct use. I mean, record variable was defined in my record itself. My TStTicket record has sub records in it. What I need to "tweak" is one of these sub types. I am not sure if I can still use that function (before and after exchanging json string) and make it work for my specific case.

Lastly, for me to have a better understanding, I have other UInt16 record variables used at the beginning ot TStTicket record

TStTicket = packed record
    TransactionFlags: UInt32;
    OptionFlags: UInt32;
    ZNo: UInt16;
    FNo: UInt16;
    EJNo: UInt16;

These seems to be fine when json serialized. Is it Integer type that is causing a problem for me?

Thanks.

Offline

#8 2016-07-12 14:27:43

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,240
Website

Re: JsonSerialization question

Try to use integer, cardinal and word types directly, not UInt32/UInt16.

Offline

#9 2016-07-12 16:05:57

sevo
Member
Registered: 2015-11-10
Posts: 27

Re: JsonSerialization question

i had this problem with Delphi 2010, too.
The rtti was missing for some records in an interface-based service.
Adding a dummy field of type string did the job.

Offline

#10 2016-07-12 16:25:11

ertank
Member
Registered: 2016-03-16
Posts: 163

Re: JsonSerialization question

@sevo, how did you add a dummy string field and *not* have it serialized in the final json string?

Offline

#11 2016-07-13 06:32:59

sevo
Member
Registered: 2015-11-10
Posts: 27

Re: JsonSerialization question

Afaik this is not automagically possible.
In my case, client and server had to ignore the dummy fields.

Offline

#12 2016-07-13 09:09:15

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,240
Website

Re: JsonSerialization question

In such cases, you may use a TPersistent/TSynPersistent or even a TSynAutoCreateField class definition (the later will have the ability to manage the livetime of nested objects, and even list of objects - serialized as JSON arrays - using T*ObjArray definitions).
See http://synopse.info/files/html/Synopse% … #TITLE_580

Offline

Board footer

Powered by FluxBB