#1 2019-11-06 08:34:09

Goulu
Member
From: Switzerland
Registered: 2018-09-18
Posts: 6
Website

buffer size related problems when streaming VCL interfaces

I use mORMot to jSONify an old VCL interface and "teleoperate" it from a webpage.

Sometime I get invalid JSON with two consecutive commas :

"sbtBase7": {
                    "ClassName": "TBSAImageButton",
                    "AutoRepeat": false,
                    "AllowAllUp": false,
                    "Anchors": [
                        "akLeft",
                        "akTop"
                    ],
                    "BiDiMode": "bdLeftToRight",
                    ,
                    "GroupIndex": 0,
                    "Down": false,
                    "Caption": "View Line",

I noticed it is related to the buffer size I assign in the constructor, the position of the double commas (8168 in the case above) is always a bit before the buffer size (8192).

Increasing the buffer size "solves" the problem, but my VCL interface needs more than 1Mb in some cases, so I preferred to "patch" the result as below :

TVCLSerializer = class(TJSONSerializer) 
...

const
  CStreamOptions: TTextWriterWriteObjectOptions = [woStoreClassName,
    woEnumSetsAsText, woInt64AsHex, woDontStoreEmptyString, woStoreStoredFalse];

constructor TVCLSerializer.Create;
begin
  inherited CreateOwnedStream(8192);
  include(fCustomOptions, twoForceJSONStandard);
  FStreamedObjects := TStreamedObjects.Create();
end;

function TVCLSerializer.ObjectToJSON(
  value: TObject;
  aName: string): RawUTF8;
begin
  Clear; // calls CancelAll
  AddString('{"' + aName + '":');
  if assigned(value) then
    WriteObject(value, CStreamOptions) // custom method
  else
    AddString(NULL_STR_VAR);
  Add('}');
  FlushToStream; // to make sure, but doesn't seem to change anything
  SetText(result);

  // ugly cure to mORMot(?) problem:
  result := StringReplace(result, ',,', ',', [rfReplaceAll]);
end;

Well, to be honest, my custom TVCLSerializer.WriteObject method is quite tricky, with calls like

  CancelLastComma; CancelLastChar('}');

to append some fields to the published properties, but it's tested with a lot of simple components (JSON shorter than 8192...).

Could it be a problem ? Should I use a different approach in ObjectToJSON ? I will try to use the stream output directly to see if it makes a difference ...

Delphi XE5.

Thanks for any advice and for your GREAT job.

Offline

#2 2019-11-06 14:33:53

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

Re: buffer size related problems when streaming VCL interfaces

Cancel* methods only work for a SINGLE char.
Calling Cancel* methods twice will fail for sure, if you are around the output buffer.

I have ensure it is clearly stated in the documentation now:
https://synopse.info/fossil/info/b6b6cc3a3d

Offline

Board footer

Powered by FluxBB