You are not logged in.
Pages: 1
Hi,
here is the code sample.
var
V, V2 : TDocVariantData;
begin
V.InitJSON('{"DATA":[{"NAME":"Name1","COMMENT":"Comment1"},{"NAME":"Name2","COMMENT":"Comment2"}],"DATA_ROWS":2}');
V2 := TDocVariantData(V.Values[0]);
Assert(V2.Kind = dvArray); // <-- here is OK
V2 := TDocVariantData(V.Value[0]);
Assert(V2.Kind = dvArray); // <- here is exception
end;
When I'm accessing Values property - it returns data as array.
When I'm accessing Value property by index or name - data kind is dvUndefined.
Is this proper behavior?
Offline
Are you sure V.Value[0] is a TDocVariantData?
I guess not, it is a variant with varByRef or varVariant type.
So writing TDocVariantData(V.Value[0]) is unsafe.
If you are not 100% sur that a variant is a TDocVariantData, first check the exact variant type by using DocVariantType.IsOfType(V.Value[0]).
See http://synopse.info/files/html/Synopse% … l#TITLE_37
But you must ensure that the variant instance is really a TDocVariant kind of data before transtyping e.g. by calling DocVariantType.IsOfType(aVariant) or the DocVariantData(aVariant)^ or DocVariantDataSafe(aVariant)^ functions, which both will work even for members returned as varByRef via late binding (e.g. V2.doc):
if DocVariantType.IsOfType(V1) then
with TDocVariantData(V1) do // direct transtyping
for i := 0 to Count-1 do // direct access to the Count: integer field
writeln(Names[ i ],'=',Values[ i ]); // direct access to the internal storage arrayswriteln(V2.doc); // will write '{"name":"john","doc":{"one":1,"two":2.5}}'
if DocVariantType.IsOfType(V2.Doc) then // will be false, since V2.Doc is a varByRef variant
writeln('never run'); // .. so TDocVariantData(V2.doc) will fail
with DocVariantData(V2.Doc)^ do // note ^ to de-reference into TDocVariantData
for i := 0 to Count-1 do // direct access the TDocVariantData methods
writeln(Names[ i] ,'=',Values[ i ]);
// will write to the console:
// one=1
// two=2.5
In practice, DocVariantDataSafe(aVariant)^ may be preferred, since DocVariantData(aVariant)^ would raise an EDocVariant exception if aVariant is not a TDocVariant, but DocVariantDataSafe(aVariant)^ would return a "fake" void DocVariant instance, in which Count=0 and Kind=dbUndefined.
In all case, there is NO benefit of using V.Value[0].
If you access at the TDocVariantData level, you should better use directly V.Values[0].
Offline
Hi,
thanks for answer.
Actually I was trying initially to access by Name, i.e. V2 := TDocVariantData(V.Value['DATA']).
If V2 := TDocVariantData(V.Values[0]) keeps the Kind = dvArray, why V.Value['DATA'] does not?
Isn't V.Value at the end taking from the same V.Values?
Offline
No, V.Value[] returns the value by reference, for obvious performance reasons.
Please read again my answer: this is a variant of type varByRef or varVariant, not directly a TDocVariantData.
So you would need to use DocVariantData() or DocVariantDataSafe() to access it.
Offline
Got it now, thanks.
Offline
Pages: 1