You are not logged in.
I don't know what to say about the > mark in the DElphi IDE.
Sounds like a Delphi IDE bug.
This seems like it. If I add the variable in Watch List it is just fine.
Sorry about all this trouble.
Thank you.
Can you debug a little more and see where it stops during deserialization?
I couldn't easily trace this in mormot codes.
I tried to use Lazarus (FPC v3.2.3, Lazarus v4.1 64bit). Project was targeting 64bit, too. This time I get "failed" message displayed.
Lazarus codes as follows
uses
mormot.core.json,
mormot.core.base;
const
cJson = '{"ccValidationResults":{"Zorunlu ürün özellikleri":{"attribute.Paket_Icerigi":["Zorunlu özellik değeri Paket İçeriği boş olamaz"],"attribute.000002C":["Zorunlu özellik değeri Kumaş Tipi boş olamaz"]}}}';
type
THepsiburadaProduct = packed record
ccValidationResults: Variant;
end;
procedure TForm1.FormCreate(Sender: TObject);
var
LProduct: THepsiburadaProduct;
begin
FillChar(LProduct, SizeOf(LProduct), 0);
if not RecordLoadJson(LProduct, RawUtf8(cJson), TypeInfo(THepsiburadaProduct)) then
ShowMessage('failed');
// Lazarus display failed message on Windows.
end;
I see function TRttiJson.ValueLoadJson returns nil and this is an error status. Code execution goes to "try if binary serialization was used" part in this function
I couldn't identify exact part of the JSON which stops the parsing.
I also tried several online JSON validator tools and simplified JSON passed as valid in all of them.
Hello,
It is my mistake that I missed the trailing comma when I copy-paste it from the JSON array. Sorry about that.
If you check the second picture, 16th item in the OP, it does not have ">" mark in debug window. The problem I am facing is some where in the middle of a JSON array not at the end or the beginning. Array item before and after are fine not the 16th item though.
Taking it as a stand alone JSON and I still can not see ">" mark in debug window.
Here is the updated project with trailing comma removed.
https://codefile.io/f/ZaODJjXb1M
Here is LProducts debug window view using the updated sample code.
https://ibb.co/Kx19YBdV
If I remove ccValidationResults from the record definition my debug window displays like below and I can expand it reading all record values separately
https://ibb.co/FqsN1530
I think there is a problem some where that I do not know the reason why. I can reproduce the same behavior on 32bit and 64bit. My problem emerged with the 64bit originally.
It feels like mORMot2 is not processing the JSON to the end and stopping at some point. I think this is might also explain random value on LProduct.price.
Hello,
I am using Delphi 12.3 and the latest mORMot2 for JSON operations from 20th July (SHA-1: 072fe3a3412a75b05522c7a5a673615ec7c97dc8 * tests: enhanced TFormatUtf8 coverage).
I have a situation that I cannot understand the reason.
Code example: https://codefile.io/f/wozJ7ViV7J
When I de-serialize a JSON it completes OK. But, I cannot use the record and its data.
Here is a screen from debug window after de-serialization completed
https://ibb.co/hFqM6tb2
There should be an arrow > displayed next to the LProduct record, but there is none.
I got a problem report that some products are not processed and I could find problematic JSON in the code example above. It is normally part of an array.
When the loop arrives to this specific element in array it is not causing any exceptions or anything but is not being processed either. Array after de-serialized is displayed as following in Delphi debug screen
https://ibb.co/fV851Lxb
Item number 16 is the sample JSON in above code snippet.
If I remove "ccValidationResults" from the record definition, there is no problem and de-serialization seems to complete OK. I can use record OK. However "price" value which is after ccValidationResults in JSON is not zero and some random number. I don't know if later is a problem or a feature.
Any help is appreciated.
Thanks & Regards,
Ertan
Hello,
I'm using Delphi and mORMot2 from 13th of January 2025 11:55 AM commit.
When serializing I would like to have enums as numbers. Is there a way to do that?
Sample code:
type
TTestEnum = (a=3, b=7, c=13);
TTestRec = packed record
aint: Integer;
aenum: TTestEnum;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
LRec: TTestRec;
LJson: string;
begin
LRec.aint := 99;
LRec.aenum := TTestEnum.b;
LJson := string(mormot.core.json.RecordSaveJson(LRec, TypeInfo(TTestRec)));
// serialized as '{"aint":99,"aenum":"07"}'
end;
Thanks & Regards,
Ertan
I was trying to learn how to do it. That _JsonFast() is working just fine.
Thank you
Hello,
There is a situation where I need to conditionally send json value as null or as a record to a server. Since there is null involved, I declared my record using variant for that specific variable.
Problem is, I couldn't figure out a way to pass a record to variant. I tried to pass a string like below (actual record is more complex than the example).
type
TRec = packed record
int: Integer;
Val: Variant; // sometimes NULL sometimes a record
end;
TRec2 = packed record
Percentage: Double;
end;
procedure TForm1.FormCreate(Sender: TObject);
var
LRec: TRec;
LRec2: TRec2;
LRecJson, LRec2Json: string;
begin
LRec2.Percentage := 1.5;
LRec2Json := string(mormot.core.json.RecordSaveJson(LRec2, TypeInfo(TRec2)));
LRec.int := 123;
LRec.Val := LRec2Json;
LRecJson := string(mormot.core.json.RecordSaveJson(LRec, TypeInfo(TRec)));
end;
Above code results below json string in LRecJson where Val contains a string value.
{"int":123,"Val":"{\"Percentage\":1.5}"}
What I am trying to achieve is to have Val contain a json object as below
{"int":123,"Val":{"Percentage":1.5}}
Is this possible using mORMot2 and records?
Thanks & Regards,
Ertan
Hello,
Below example fails using Delphi 12.
uses
mormot.core.json, mormot.core.base;
type TRec = packed record id: Integer; atime: TTime; end;
procedure TForm1.FormCreate(Sender: TObject);
const cData = '{id:123,atime:"15:30"}';
var LRec: TRec;
begin
if not mormot.core.json.RecordLoadJson(LRec, RawUtf8(cData), TypeInfo(TRec)) then
ShowMessage('not ok')
else
ShowMessage('deserialize completed');
end;
I know I can use TDateTime instead. Just asking for convenience. Is it possible to support TTime data type?
Thank you for your consideration.
Regards,
Ertan
You can overwrite the TDateTime format, but it would be global for the whole process.
I don't know how I can do that?
I am returning back to this specific date time format.
I see it can be de-serialized successfully into TDateTime if the field name is "timestamp" like below
type
TRec = packed record
timestamp: TDateTime;
end;
procedure TForm1.FormCreate(Sender: TObject);
const cData = '{"timestamp":"2024-08-02 21:02:13"}';
var LRec: TRec;
begin
mormot.core.json.RecordLoadJson(LRec, RawUtf8(cData), TypeInfo(TRec));
end;
I wonder if it is possible to widen this for TDateTime definitions using any name?
Thank you for your consideration.
Regards,
Ertan
That's working.
Thank you.
Hello,
I am using Delphi 12.2, mORMot from GitHub January 3, 2025 update.
Is it possible to have mORMot2 de-serialize to auto convert Unix Time (with/without milliseconds) Int64 values to TDateTime?
uses
System.DateUtils, mormot.core.json, mormot.core.base;
type
TTest = packed record
ADate: TDateTime;
end;
procedure TForm1.FormCreate(Sender: TObject);
const cTest = '{"adate":1736705403567}'; // with milliseconds
var LRec: TTest;
begin
mormot.core.json.RecordLoadJson(LRec, RawUtf8(cTest), TypeInfo(TTest));
ShowMessage(LRec.ADate.ToString());
end;
Above code cause an overflow (if turned on)
Thanks & Regards,
Ertan
Hello,
There are some web services insisting on "yyyy-mm-dd hh:nn:ss" format. Sometimes they even put only php format string "Y-m-d H:i:s" as their requirement.
Is it possible to have mORMot2 to serialize TDateTime values using a custom format?
Thanks & Regards,
Ertan
Tested and found no problems.
Thank you.
Hello,
I am using Delphi 12.2 and mORMot2 from September 24, 2024
As to my tests below code sample is not de-serialized
uses
mormot.core.base,
mormot.core.json;
type
TTest = packed record
adate: TDate;
end;
procedure TForm1.Button1Click(Sender: TObject);
const
cTest = '{"adate":"2025-01-01"}';
var
LData: TTest;
begin
mormot.core.json.RecordLoadJson(LData, RawUtf8(cTest), TypeInfo(TTest));
end;
The same json string can be de-serialized if I change TDate -> TDateTime in record.
I wonder if TDate datatype is not supported?
Thanks & Regards,
Ertan
I didn't know that mORMot2 has such ability and also that it is turned on by default.
I spotted that I missed several breaking format differences in the web service response.
Sorry about the noise.
Hello,
There is this java web service which is requesting and responding using the identical JSON format.
I have below record definition. That record is serialized and sent to the web service. There is no problem and it consumes it.
THuginTPSSaleOrderSaleItem = packed record
Quantity: Double;
Amount: Double;
PLUNo: Integer;
DepartmentId: Integer;
VatRate: Double;
end;
But, the web service is responding something like below
{
"Quantity": "2.00",
"Amount": "10.00",
"PLUNo": 1,
"DepartmentId": 1,
"VatRate": 0,
}
As you can see the web service respond has some numbers as double quoted (aka string).
I wonder if mORMot2 can de-serialize these numbers in double data type as defined in the record.
If it is possible, I do appreciate a small RecordLoadJson() example showing how I can build necessary parameters and pass them to the function.
Thanks & Regards,
Ertan
P.S. Both record and json examples are greatly minimized for keeping this post short.
I couldn't understand what I read from the document so I did some tests.
Base information
type
TTransaction = packed record
TxnId: Int64;
TxnTypeId: Int64;
end;
const
__TTransaction = 'TxnId Int64 TxnTypeId Int64';
var
Json: string = '{"test":"additional field","TxnId":1,"TxnTypeId":2}';
...
initialization
Rtti.RegisterFromText(TypeInfo(TTransaction), __TTransaction);
Tests I did are as follows:
// Test1 - no dialog displayed
if mormot.core.json.RecordLoadJson(Test, Json, TypeInfo(TTransaction), nil, False) then
ShowMessage('OK');
// Test2 - displays OK dialog
if mormot.core.json.RecordLoadJson(Test, Json, TypeInfo(TTransaction)) then
ShowMessage('OK');
Test2 is what I currently have in my unit using Synopse.pas.
It seems I don't need any additional code change as "Tolerant = true" as default and that is what I needed.
Thanks & Regards,
Ertan
Thank you. In file search returns so many results and repeated filenames that it seems I missed that note.
So, how can I tell mORMot2 to read ignore unknown fields?
Hello,
I have old code that I am converting to use mORMot2 and I have quite a lot code like below
const
__TTransaction = 'TxnId Int64 TxnTypeId Int64';
...
initialization
TTextWriter.RegisterCustomJSONSerializerFromText(TypeInfo(TIngenicoResult), __TTransaction).Options := [soReadIgnoreUnknownFields];
I could not figure how I can put this so it will work the same as before.
Any help is appreciated.
Thanks & Regards,
Ertan
After calculations, I get 1.92KB per item average memory usage. It was around 5KB before.
That would suffice to continue with Win32 application.
Since increase is slow, I will figure an alternative solution in the future.
Thanks.
TDocVariant loads everything into memory, before you can iterate into its values.
Yes, I am going to make measurements. Getting ready for it.
I count on dvoInternNames, dvoInternValues parameters. I will see if it will be enough to keep memory very low as names identically repeat and there are values that repeat a lot.
1. I have changed the BOM support in mORMot 2, and now you can use Doc.InitJsonFromFile() with a BOM file.
Even if BOM is not a good idea for UTF-8...
InitJsonInPlace() is indeed low-level.
I do really appreciate that. Thank you. I also think BOM is not a good idea, but you eventually find it out of your control here and there.
2. I guess you can use dvoInternNames safely, but only dvoInternValues if most JSON values are likely to reappear in the input JSON.
Number values indeed repeat a lot like 1 and 2 only and that is for multiple different values.
3. If TDocVariant has troubles with the JSON, and if the structure is really simple, I would rather try to use a dynamic array of records for the storage.
It would be more efficient in terms of memory, and also performance. And using a dynamic array and records would be much easier to work with.
That file immediately goes into database for each item read. I will not keep its data in memory for any other purpose. So far TDocVariant seems to work just fine.
My mistake again, I assumed InitJSONInPlace returns Boolean, but it does not.
if Doc.InitJSONInPlace(Pointer(AnyTextFileToRawUtf8('users.json')), [dvoInternNames, dvoInternValues]) = nil then
begin
ShowMessage('Json file could not be loaded');
Exit();
end;
Now, I will go back to parsing and measure memory usage on my test data.
Thanks.
Try TDocVariantData.InitJSONInPlace(AnyTextFileToRawUtf8(FilePath));
I could not make compiler happy. InitJSONInPlace require PUTF8Char and AnyTextFileToRawUtf8 returns RawUTF8. However, compiler says
[dcc32 Error] Unit1.pas(44): E2010 Incompatible types: 'PUtf8Char' and 'UTF8String'
I tried several other conversion and explicitly using pointers. But, all of them lead to a compiler error.
Hello,
Problem was users.json file has BOM and so cannot be read by TDocVariantData.InitJsonFromFile() If I read it using TFile.ReadAllText('users.json', TEncoding.UTF8) it is just fine. However, reading file content in a text variable and then using it to Init TDocVariantData feels like additional memory usage especially on a considerably large file.
This file is received as ZIP format from a web service and I cannot change the way it is saved. Is there any option for TDocVariantData.InitJsonFromFile() that can possible make it work with files including BOM?
Thanks & Regards,
Ertan
I've never used TDocVariantData and I cannot find my way thru. Below is my current test code, but even if it is an json of array, code thinks otherwise and exits at Doc.IsArray check.
uses
mormot.core.variants, mormot.core.data;
procedure TForm1.Button1Click(Sender: TObject);
var
Doc: TDocVariantData;
I, TempInteger: Integer;
TempString: string;
begin
Doc.InitJsonFromFile('users.json', [dvoInternNames, dvoInternValues]);
if not Doc.IsArray then Exit();
repeat
TempString := Doc.GetValueOrEmpty('Identifier');
TempInteger := string('0' + Doc.GetValueOrEmpty('AppType')).ToInteger();
until (not Doc.Items.MoveNext);
end;
Can someone put me in right direction, please?
Thanks & Regards,
Ertan
Hello,
I have a well defined structured relatively big (195MiB) json file to parse. Using Delphi System.JSON unit it will likely crash on Win32 exe because average single structure needs around 5KB in memory. The file has more than 750.000 records and slowly increasing.
I could find about 5 threads in forum about "SAX". I could not find anything in documents. I believe (correct me if I am wrong) mORMot and very much likely mORMot2 has SAX json parsing.
I do appreciate an example on how to use SAX parsing, please.
BTW, I prefer mORMot2.
Thanks & Regards,
Ertan
A good reference for future.
Thank you.
This was what I have been looking for.
Both name and unit change and I failed to find it in mORMot2 sources.
Thank you.
Hi,
I have an old project that I need to make some changes and additons. I am using mORMot 1 in that project for json handling and now I want to switch using mORMot2.
But, I could not find any example project or some information (even on this forum) to adapt my code. It is more than possible I overlooked at it.
There is ThirdPartyDemos\martin-doyle\03-MethodBasedServices example project which has very basic json handling and that is all I could find.
I do not know if having just "mormot.core.json" is enough in uses list.
TTextWriter.RegisterCustomJSONSerializerFromText() is something that I use in old project and I could not see how to use/convert it to mORMot2.
I am also not quite sure how to serialize/de-serialize arrays and regular json.
Any help is appreciated.
Thanks & Regards,
Ertan
Hello,
I was more asking about (2) "IVAtBeginning" implementation. This is the part I could not figure.
Hello,
I am using Delphi 10.4.2, targeting Android32.
There is a previously developed REST web service with MARS Curiosity project which is using mORMot encryption routines. That web server running on Windows and is just fine. Now, I have to develop a small mobile application that is consuming some methods on that web service. Unfortunately, I failed to compile below function on Android32. I get error for SynLZ unit for its asm instructions. It uses SynCommons and SynCrypt units on Win32 platform.
function EncryptItAES(const s: string; const AKey: TBytes): string;
var
Key: TSHA256Digest;
Aes: TAESCFB;
_s: RawByteString;
begin
Result := EmptyStr;
Key := SHA256Digest(Pointer(AKey), Length(AKey));
Aes := TAESCFB.Create(Key, 256);
try
_s := StringToUTF8(s);
_s := BinToBase64(Aes.EncryptPKCS7(_s, True));
Result := UTF8ToString(_s);
finally
Aes.Free();
end;
end;
1) I wonder if I use mORMot2 encryption routines under Android32 and write similar function to above?
2) I can use alternative AES encryption library for Android32. I just don't know how above code each time produce different encrypt data for same input. I appreciate instructions on how to develop same logic using AES library that compiles under Android32? I am confused by checking sources to figure this out.
Thanks & Regards,
Ertan
Nevermind, just figured, right after I post that there is a space character in raw JSON string for
"isSelected "
Cost me a lot of time until I could actually see that.
Sorry for the noise.
Hello,
I am using Delphi 10.3, mORMot SynopseCommit.inc value '1.18.6244'
I could not figure why I get FAILED! message for following simple JSON string
{
"optionUuid": "57202ea4-cc62-4eff-bbea-fa5be41449ee",
"optionName": "Tuzsuz",
"optionPrice": 5.2,
"isSelected ": true
}
Using a code like below:
TOrderProductNote = packed record
optionUuid: string;
optionName: string;
optionPrice: Double;
isSelected: Boolean;
end;
procedure TForm2.Button1Click(Sender: TObject);
var
Response: TOrderProductNote;
TempString: string;
begin
TempString := '{"optionUuid": "57202ea4-cc62-4eff-bbea-fa5be41449ee","optionName": "Tuzsuz","optionPrice": 5.2,"isSelected ": true}';
if not SynCommons.RecordLoadJSON(Response, RawUTF8(TempString), TypeInfo(TOrderProductNote)) then
ShowMessage('FAILED!')
else
ShowMessage('OK');
end;
My debugging, I see de-serialization fails on "isSelected", but I could not understand why.
Any help is appreciated.
Thanks & Regards,
Ertan
Hello,
I tried to search in the forum without any success.
I receive a JSON string as following:
"lastPriceChangeDate": 1616569735683,
"lastStockChangeDate": 1618009761506,
"lastUpdateDate": 1618009761506,
This is a Unix Timestamp in milliseconds format.
Can I directly de-serialize that kind of values into to a TDateTime variable using mORMot?
Thanks & Regards,
Ertan
Hello,
I am trying to make an integration with an online food sale chain. They have kind of weird design. I am getting a JSON (part of it) as below:
"optionCategories": [
{
"optionCategory": "5dd28622e0450549407168f4",
"name": {
"tr": "1. Tantuni Tercihi",
"en": "1. Tantuni Tercihi"
},
"options": [
{
"option": "5dd28622e045052fb27168f6",
"product": "5dd28614c424f0658e8cedb8",
"name": {
"tr": "Yarım Ekmek Et Tantuni",
"en": "Yarım Ekmek Et Tantuni"
},
"price": 0,
"optionCategories": [
{
"optionCategory": "5dd28614c424f010da8cedb9",
"name": {
"tr": "Porsiyon Tercihi",
"en": "Porsiyon Tercihi"
},
"options": [
{
"option": "5dd28614c424f05bd58cedbc",
"name": {
"tr": "1 Porsiyon",
"en": "1 Porsiyon"
},
"price": 0
}
]
}
]
}
]
I could not figure how I should be preparing my record structure in order to be able to de-serialize something like that. I am actually stuck where "optionCategories" is becoming recursive. And there is another part where it is not going recursive. So, it is not always it is recursive, but sometimes. Here is an example for not recursive part (this also comes in identical array):
{
"optionCategory": "5dd28622e04505a7b37168ee",
"name": {
"tr": "İçecek Tercihi",
"en": "İçecek Tercihi"
},
"options": [
{
"option": "5dd28622e045052a3f7168ef",
"product": "5dd2861f35e9bba43d19b039",
"name": {
"tr": "Eker Ayran (300 ml)",
"en": "Eker Ayran (300 ml)"
},
"price": 0
}
]
}
My current record structure (part of it) is not working and is as following:
TName = packed record
tr: string;
en: string;
end;
TOption = packed record
option: string;
product: string;
name: TName;
price: Double;
end;
TOptions = TArray<TOption>;
TOptionCategory = packed record
optionCategory: string;
name: TName;
options: TOptions;
end;
TOptionCategories = TArray<TOptionCategory>;
I really do not want to parse whole JSON manually.
I appreciate any help.
Thanks & Regards,
Ertan
That worked just fine.
Pointer(TestBytes) generates identical hash.
Thank you.
Hello,
I am using Delphi 10.3.3, Synopse commit version 1.18.6045, generating Win32 executable.
I had some legacy code that I am modifying. I used to pass parameter as array of byte and now I am changing it into TBytes. However, I am getting different result for same byte values. My test code is as following:
uses
SynCrypto;
const
TestArray: Array [0..5] of Byte = (1, 2, 3, 4, 5, 6);
TestBytes: TBytes = [1, 2, 3, 4, 5, 6];
procedure TForm1.Button1Click(Sender: TObject);
var
Sha2561: TSHA256Digest;
Sha2562: TSHA256Digest;
begin
Sha2561 := SHA256Digest(Pointer(@TestArray), SizeOf(TestArray));
Sha2562 := SHA256Digest(Pointer(@TestBytes), Length(TestBytes)); // For TBytes I must use Length, SizeOf always returns 4
if not CompareMem(@Sha2561, @Sha2562, 32) then
ShowMessage('different')
else
ShowMessage('identical');
end;
For above test, I get different message displayed.
I am not sure if I am doing something wrong. I could not remember why I did write a code like
Pointer(@TestArray)
That code is possibly a copy-paste from this forum, years ago. In any way, using it as
@TestArray
also displays different message for me.
Any help is appreciated.
Thanks & Regards,
Ertan
Missed that point in samples.
Thanks for clarifying.
Hello,
I am using Delphi 7 and latest available version of Synopse from GitHub. Just removed all SynCommons.pas files from my system and have just a single copy.
Registering a custom json text writer fails for me. Details are as following:
type
TTicker = packed record
symbol: RawUTF8;
highPrice: Double;
lowPrice: Double;
end;
TTickers = Array of TTicker;
const
__TTickers = '[symbol RawUTF8 highPrice Double lowPrice Double]';
initialization
TTextWriter.RegisterCustomJSONSerializerFromText(TypeInfo(TTickers), __TTickers);
end;
I am getting error saying:
TTicker text definition is not accurate, or the type has not been defined as packed record: RTTI size is 20 bytes but text definition covers 0 bytes
I cannot see where I am doing it wrong.
Any help is appreciated.
Thanks & regards,
Ertan
Thanks for all suggestions.
Actually, I did take very basic precautions like try..except block in my code. I did not put it all here in my earlier post.
...
try
V := _Json(RetJsonString);
except
// do what needs to be done
end;
...
After reading other replies, I also changed my code to retrieve data like following:
var
Amount: Integer;
LStPayment: TVariantDynArray;
begin
LStPayment := _Safe(V.stPayment).Values;
for Idx := 0 to High(LStPayment) do
begin
if LStPayment[Idx].typeOfPayment = 4 then
begin
Amount := LStPayment[Idx].StBankPayment.Amount;
end;
end;
end;
Which IMHO is easier to compared to my initial version. However, I am not quite sure this code above is free from exceptions if there is no StBankPayment exists in LStPayment (even though it should exists because payment type 4 means credit card payment) I am asking just in case. Because even rarely it does happen when company does an update to device software and breaks produced json in a way.
I appreciate if someone can confirm/deny.
Regards,
Ertan
Seems I need to use array access as following:
...
V := _Json(RetJsonString);
...
var
Amount: Integer;
AType: Integer;
begin
if V.StPayment._(0).typeOfPayment = 4 then
begin
Amount := V.StPayment._(0).StBankPayment.Amount;
end;
end;
Problem solved.
Thanks.
That did indeed work.
I gave up and follow igors233 suggestion. As I do not know how to use TDocVariantData. I did read documents but could not comprehend them fast enough. So, I went down using Variant.
However, I could failed to read information I am looking for from sub objects in incoming json. For regular record filled with data I could write something like:
var
Amount: Integer;
AType: Integer;
begin
if Rec.StPayment[0].typeOfPayment = 4 then
begin
Amount := Rec.StPayment[0].StBankPayment.Amount;
end;
Now, I load json into a Variant named V. Try to write a code as below:
...
V := _Json(RetJsonString);
...
var
Amount: Integer;
AType: Integer;
begin
if V.StPayment[0].typeOfPayment = 4 then
begin
Amount := V.StPayment[0].StBankPayment.Amount;
end;
That compiles fine, but fails at the if statement at run-time.
I appreciate some examples as to how I can extract json data directly from a variant.
Thanks & regards,
Ertan
I do not know details of RTTI. However, below code works for the first one and not for the second one. I do get "json2 OK" displayed on the screen. That is without using any of suggested 3 options above.
const
Json = '[{"u32VAT":15,"u32Amount":100,"u16VATPercentage":1800},{"u32VAT":0,"u32Amount":0,"u16VATPercentage":0},{"u32VAT":0,"u32Amount":0,"u16VATPercentage":800},{"u32VAT":0,"u32Amount":0,"u16VATPercentage":100},' +
'{"u32VAT":0,"u32Amount":0,"u16VATPercentage":2400},{"u32VAT":0,"u32Amount":0,"u16VATPercentage":0},{"u32VAT":0,"u32Amount":0,"u16VATPercentage":0},{"u32VAT":0,"u32Amount":0,"u16VATPercentage":0}]';
Json2 = '{"u32VAT":15,"u32Amount":100,"u16VATPercentage":1800}';
procedure TForm3.Button1Click(Sender: TObject);
var
Taxes: TStVATDetails;
Tax: TStVATDetail;
begin
if SynCommons.RecordLoadJSON(Tax, RawUTF8(Json2), TypeInfo(TStVATDetail)) then
ShowMessage('json2 OK')
else
ShowMessage('json2 failed');
if not SynCommons.DynArrayLoadJSON(Taxes, RawUTF8(Json), TypeInfo(TStVATDetails)) then
begin
ShowMessage('Cannot deserialize Json!');
end
else
begin
ShowMessage('Json deserialization OK');
end;
end;
There is an overloaded version of DynArrayLoadJSON in SynCommons.pas. My code supposed to use it
function DynArrayLoadJSON(var Value; const JSON: RawUTF8; TypeInfo: pointer): boolean;
var tmp: TSynTempBuffer;
begin
tmp.Init(JSON); // make private copy before in-place decoding
try
result := DynArrayLoadJSON(Value,tmp.buf,TypeInfo)<>nil;
finally
tmp.Done;
end;
end;
Hello,
I am using Delphi 10.3.3, Synopse is updated from github. I double check that I am using latest version of SynCommons.pas
I have a simple json string (json array) that I fail to find why I cannot de-serialize. I simply fail to find a reason.
I do appreciate any help.
Record definition:
TStVATDetail = packed record
u32VAT: Integer;
u32Amount: Integer;
u16VATPercentage: UInt16;
end;
TStVATDetails = Array of TStVATDetail;
Json array that I cannot de-serialize:
[{"u32VAT":15,"u32Amount":100,"u16VATPercentage":1800},{"u32VAT":0,"u32Amount":0,"u16VATPercentage":0},{"u32VAT":0,"u32Amount":0,"u16VATPercentage":800},{"u32VAT":0,"u32Amount":0,"u16VATPercentage":100},{"u32VAT":0,"u32Amount":0,"u16VATPercentage":2400},{"u32VAT":0,"u32Amount":0,"u16VATPercentage":0},{"u32VAT":0,"u32Amount":0,"u16VATPercentage":0},{"u32VAT":0,"u32Amount":0,"u16VATPercentage":0}]
My code for de-serialization:
const
Json = '[{"u32VAT":15,"u32Amount":100,"u16VATPercentage":1800},{"u32VAT":0,"u32Amount":0,"u16VATPercentage":0},{"u32VAT":0,"u32Amount":0,"u16VATPercentage":800},{"u32VAT":0,"u32Amount":0,"u16VATPercentage":100},' +
'{"u32VAT":0,"u32Amount":0,"u16VATPercentage":2400},{"u32VAT":0,"u32Amount":0,"u16VATPercentage":0},{"u32VAT":0,"u32Amount":0,"u16VATPercentage":0},{"u32VAT":0,"u32Amount":0,"u16VATPercentage":0}]';
procedure TForm3.Button1Click(Sender: TObject);
var
Taxes: TStVATDetails;
begin
if not SynCommons.DynArrayLoadJSON(Taxes, RawUTF8(Json), TypeInfo(TStVATDetails)) then
begin
ShowMessage('Cannot deserialize Json!');
end
else
begin
ShowMessage('Json deserialization OK');
end;
end;
Hello,
I have a problem de-serializing a json string. After I get false from de-serialization function, I see some variables have value in my record.
In order to find my mistake, I would like to understand how mORMot doing de-serializing order.
For example I have below json string:
{"name":"test","surname":"test"}
And my record definition is:
type
TPerson = packed record
surname: string;
name: string;
end;
When de-serializing, is it name or surname that is filled in record variable first?
Thanks & regards,
Ertan
I do really would like to hear if somebody can re-produce issue I am facing.