You are not logged in.
Pages: 1
Thanks but AddFrom doesn't work (Delphi XE5) I get E2010 Incompatible types: 'Variant' and 'TDocVariantData'
I wrote this, but still have problem with some complexe requests :
function MergeParams(
inplace: TDocVariantData;
const toadd: TDocVariantData): TDocVariantData;
var
i: integer;
n: string;
v: variant;
begin
// inplace.AddFrom(toadd); // E2010 Incompatible types: 'Variant' and 'TDocVariantData'
for i := 0 to toadd.Count - 1 do begin
n := toadd.Names[i];
if n <> '' then
inplace.AddValue(n, toadd[i])
end;
result := inplace;
end;
I have a simple server derived from TSQLHttpServer that overrides function Request(Ctxt: TServerRequest)
in this function I extract params passed in the Ctxt.url using my own code (did not find it in SynCommons...) that returns them as a TDocVariantData
and I extract other params with InitJSON(Ctxt.InContent) which also returns a TDocVariantData
How can I merge both to have all my params regardless on how they are passed ?
Or did I miss the function that does both ?
Thanks !
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.
Perfect ! Thanks !
I have custom class serializers that calls aJSONSerializer.AddJSONEscape(['pairof',Fields]),
but I notice the Fields aren't written using the options I passed to the calling ObjectToJSON(myObject, myTextWriterWriteObjectOptions)
because in
procedure TTextWriter.AddJSONEscape(const V: TVarRec);
begin
with V do
case VType of
(* other cases *)
vtObject: WriteObject(VObject); // has no Options
end;
end;
Did I miss something ?
I came across your (great) TDynArray while trying to add support for dynamic arrays to our ClassStreamer which streams published properties in XML.
I have something like this:
TheObjValue := GetObjectProp(AClass, APPropInfo);
TheTypeInfo := APPropInfo.PropType^;
case TheTypeInfo^.Kind of
tkClass : begin
if TheObjValue is TStrings then
TheStrConfig.AddValue(string(APPropInfo^.Name), TStrings(TheObjValue).Text)
else begin
AddObj(TheObjValue, string(APPropInfo^.Name), false);
end; //else
end; // tkClass
tkDynArray : begin
TheElTypeInfo := TheTypeInfo.TypeData^.elType2^; // .eltype returns nil on XE5
TheObjValue := GetObjectProp(AClass, APPropInfo);
TheArray.InitSpecific(TheTypeInfo,TheObjValue, djObject); // Why not TheElTypeInfo.Kind ?
LBuffer := JSONtoXML(TheArray.SaveToJSON());
TheStrConfig.AddValue(string(APPropInfo^.Name), LBuffer);
end // tkClass
else if TheTypeInfo^.Kind in KNOW_TYPE_KIND then begin
LVal := GetPropValue(AClass, string(APPropInfo^.Name));
TheStrConfig.AddValue(string(APPropInfo^.Name), LVal);
end //else if
end; // case
A few stupid questions and remarks:
1. in TDynArray.Init I had to add
fElemType := PTypeInfo(aTypeInfo)^.elType;
if fElemType = nil then
fElemType := PTypeInfo(aTypeInfo)^.elType2;
if fElemType<>nil then begin
to have something in my array. It probably needs to be guarded by $ifdef for other compilers (I use XE5)
2. why does TDynArray.InitSpecific require a TDynArrayKind and not a TTypeKind ? They look similar and it would be very handy... or am I missing something ?
3. TheArray.SaveToJSON() produces an array with the adresses of the TObject s in the array, which is a good start ... but how should I stream the objects themselves ?
Sorry for the Noob questions... A short link to a tutorial or example code will do as well as a long answer...
Thank you very much !
Pages: 1