You are not logged in.
Hi @ab,
I serialize a dynamic RawUTF8 array as JSON, then unserialize the JSON in a TDocVariantData and last element is losed.
The client application serialize to JSON array:
...
fContactDataQueueDynArray: TDynArray;
...
fContactDataQueueDynArray.Init(TypeInfo(TRawUTF8DynArray), fContactDataQueueArray);
... // fill the array
lData := fContactDataQueueDynArray.SaveToJSON; // lData is RawJSON type and fContactDataQueueDynArray content JSON objects
...
fContactService.RestoreContactFromQueue(aTableId, lData); // invoke the remote service
...
The server application unserialize from JSON array:
...
lContactDataQueue.InitJSON(aQueue, [dvoJSONObjectParseWithinString]); // lContactDataQueue is TDocVariantData type
...
lCount := lContactDataQueue.Count; // HERE "Count" have one less than the elements in the array
...
TDocVariantData.InitJSON with [dvoJSONObjectParseWithinString] option doesn't update correctly the VCount internal property.
The code with problem is:
function TDocVariantData.InitJSONInPlace(JSON: PUTF8Char;
aOptions: TDocVariantOptions; aEndOfObject: PUTF8Char): PUTF8Char;
var EndOfObject: AnsiChar;
Name: PUTF8Char;
NameLen, n: integer;
intnames, intvalues: TRawUTF8Interning;
begin
Init(aOptions);
...
if n>0 then begin
SetLength(VValue,n);
repeat
if VCount>=n then
exit; // unexpected array size means invalid JSON
GetJSONToAnyVariant(VValue[VCount],JSON,@EndOfObject,@VOptions,false);
if JSON=nil then
exit;
if intvalues<>nil then
intvalues.UniqueVariant(VValue[VCount]);
inc(VCount);
until EndOfObject=']';
end else
...
my patch:
function TDocVariantData.InitJSONInPlace(JSON: PUTF8Char;
aOptions: TDocVariantOptions; aEndOfObject: PUTF8Char): PUTF8Char;
var EndOfObject: AnsiChar;
Name: PUTF8Char;
NameLen, n: integer;
intnames, intvalues: TRawUTF8Interning;
begin
Init(aOptions);
...
if n>0 then begin
SetLength(VValue,n);
repeat
if VCount>=n then
exit; // unexpected array size means invalid JSON
GetJSONToAnyVariant(VValue[VCount],JSON,@EndOfObject,@VOptions,false);
if JSON=nil then begin
if EndOfObject=']' then // <--- THE PATCH
inc(VCount);
exit;
end;
if intvalues<>nil then
intvalues.UniqueVariant(VValue[VCount]);
inc(VCount);
until EndOfObject=']';
end else
...
Surely you can correct this the better way.
Thanks.
Esteban
Offline
First of all, I don't understand why you are using dvoJSONObjectParseWithinString option here.
You could just transmit lData as RawJSON (or even variant) to the RestoreContactFromQueue() service, with string escape.
I guess the root problem comes from here.
Your patch is not clear to me as a right solution, since I don't really understand what occurs here.
GetJSONToAnyVariant() returns JSON=nil in case of unexpected end - internally using GetJSONField() - so if it returns nil then there is something unexpected...
Do you have simple code to reproduce the problem?
Online
Hi @ab, the test case that reproduce the problem is here https://drive.google.com/open?id=1dYnHr … lDFq740vzm
Thanks.
Esteban
Offline
@ab, can you see the problem ?
Esteban
Offline
Now I've seen the issue.
Please check https://synopse.info/fossil/info/7200dbe52a
Thanks for the feedback!
Online
Works fine.
Thank you.
Esteban
Offline