* Do not allow duplicate keys in JSONObject

git-svn-id: trunk@38908 -
This commit is contained in:
michael 2018-05-05 14:51:19 +00:00
parent b8378ef774
commit f540dbfab3
3 changed files with 403 additions and 477 deletions

View File

@ -470,6 +470,7 @@ Type
ObjEndSeps : Array[Boolean] of TJSONStringType = (' }','}'); ObjEndSeps : Array[Boolean] of TJSONStringType = (' }','}');
Class var FUnquotedMemberNames: Boolean; Class var FUnquotedMemberNames: Boolean;
Class var FObjStartSep,FObjEndSep,FElementEnd,FElementStart : TJSONStringType; Class var FObjStartSep,FObjEndSep,FElementEnd,FElementStart : TJSONStringType;
function DoAdd(const AName: TJSONStringType; AValue: TJSONData; FreeOnError: Boolean=True): Integer;
Class procedure DetermineElementQuotes; Class procedure DetermineElementQuotes;
Private Private
FHash : TFPHashObjectList; // Careful : Names limited to 255 chars. FHash : TFPHashObjectList; // Careful : Names limited to 255 chars.
@ -638,6 +639,7 @@ Resourcestring
SErrOddNumber = 'TJSONObject must be constructed with name,value pairs'; SErrOddNumber = 'TJSONObject must be constructed with name,value pairs';
SErrNameMustBeString = 'TJSONObject constructor element name at pos %d is not a string'; SErrNameMustBeString = 'TJSONObject constructor element name at pos %d is not a string';
SErrNonexistentElement = 'Unknown object member: "%s"'; SErrNonexistentElement = 'Unknown object member: "%s"';
SErrDuplicateValue = 'Duplicate object member: "%s"';
SErrPathElementNotFound = 'Path "%s" invalid: element "%s" not found.'; SErrPathElementNotFound = 'Path "%s" invalid: element "%s" not found.';
SErrWrongInstanceClass = 'Cannot set instance class: %s does not descend from %s.'; SErrWrongInstanceClass = 'Cannot set instance class: %s does not descend from %s.';
SErrNoParserHandler = 'No JSON parser handler installed. Recompile your project with the jsonparser unit included'; SErrNoParserHandler = 'No JSON parser handler installed. Recompile your project with the jsonparser unit included';
@ -2943,58 +2945,69 @@ begin
FHash.Clear; FHash.Clear;
end; end;
function TJSONObject.DoAdd(const AName: TJSONStringType; AValue: TJSONData; FreeOnError : Boolean = True): Integer;
begin
if (IndexOfName(aName)<>-1) then
begin
if FreeOnError then
FreeAndNil(AValue);
DoError(SErrDuplicateValue,[aName]);
end;
Result:=FHash.Add(AName,AValue);
end;
function TJSONObject.Add(const AName: TJSONStringType; AValue: TJSONData function TJSONObject.Add(const AName: TJSONStringType; AValue: TJSONData
): Integer; ): Integer;
begin begin
Result:=FHash.Add(AName,AValue); Result:=DoAdd(aName,AValue,False);
end; end;
function TJSONObject.Add(const AName: TJSONStringType; AValue: Boolean function TJSONObject.Add(const AName: TJSONStringType; AValue: Boolean
): Integer; ): Integer;
begin begin
Result:=Add(AName,CreateJSON(AValue)); Result:=DoAdd(AName,CreateJSON(AValue));
end; end;
function TJSONObject.Add(const AName: TJSONStringType; AValue: TJSONFloat): Integer; function TJSONObject.Add(const AName: TJSONStringType; AValue: TJSONFloat): Integer;
begin begin
Result:=Add(AName,CreateJSON(AValue)); Result:=DoAdd(AName,CreateJSON(AValue));
end; end;
function TJSONObject.Add(const AName, AValue: TJSONStringType): Integer; function TJSONObject.Add(const AName, AValue: TJSONStringType): Integer;
begin begin
Result:=Add(AName,CreateJSON(AValue)); Result:=DoAdd(AName,CreateJSON(AValue));
end; end;
function TJSONObject.Add(const AName: String; AValue: TJSONUnicodeStringType function TJSONObject.Add(const AName: String; AValue: TJSONUnicodeStringType
): Integer; ): Integer;
begin begin
Result:=Add(AName,CreateJSON(AValue)); Result:=DoAdd(AName,CreateJSON(AValue));
end; end;
function TJSONObject.Add(const AName: TJSONStringType; Avalue: Integer): Integer; function TJSONObject.Add(const AName: TJSONStringType; Avalue: Integer): Integer;
begin begin
Result:=Add(AName,CreateJSON(AValue)); Result:=DoAdd(AName,CreateJSON(AValue));
end; end;
function TJSONObject.Add(const AName: TJSONStringType; Avalue: Int64): Integer; function TJSONObject.Add(const AName: TJSONStringType; Avalue: Int64): Integer;
begin begin
Result:=Add(AName,CreateJSON(AValue)); Result:=DoAdd(AName,CreateJSON(AValue));
end; end;
function TJSONObject.Add(const AName: TJSONStringType; Avalue: QWord): Integer; function TJSONObject.Add(const AName: TJSONStringType; Avalue: QWord): Integer;
begin begin
Result:=Add(AName,CreateJSON(AValue)); Result:=DoAdd(AName,CreateJSON(AValue));
end; end;
function TJSONObject.Add(const AName: TJSONStringType): Integer; function TJSONObject.Add(const AName: TJSONStringType): Integer;
begin begin
Result:=Add(AName,CreateJSON); Result:=DoAdd(AName,CreateJSON);
end; end;
function TJSONObject.Add(const AName: TJSONStringType; AValue: TJSONArray function TJSONObject.Add(const AName: TJSONStringType; AValue: TJSONArray
): Integer; ): Integer;
begin begin
Result:=Add(AName,TJSONData(AValue)); Result:=DoAdd(AName,TJSONData(AValue),False);
end; end;
procedure TJSONObject.Delete(Index: Integer); procedure TJSONObject.Delete(Index: Integer);

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<CONFIG> <CONFIG>
<ProjectOptions> <ProjectOptions>
<Version Value="10"/> <Version Value="11"/>
<General> <General>
<Flags> <Flags>
<SaveOnlyProjectUnits Value="True"/> <SaveOnlyProjectUnits Value="True"/>
@ -21,10 +21,18 @@
</PublishOptions> </PublishOptions>
<RunParams> <RunParams>
<local> <local>
<FormatVersion Value="1"/>
<CommandLineParams Value="--suite=TTestParser.TestArray"/> <CommandLineParams Value="--suite=TTestParser.TestArray"/>
<LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/> <LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
</local> </local>
<FormatVersion Value="2"/>
<Modes Count="1">
<Mode0 Name="default">
<local>
<CommandLineParams Value="--suite=TTestParser.TestArray"/>
<LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
</local>
</Mode0>
</Modes>
</RunParams> </RunParams>
<RequiredPackages Count="1"> <RequiredPackages Count="1">
<Item1> <Item1>

View File

@ -19,7 +19,7 @@ unit testjsondata;
interface interface
uses uses
Classes, SysUtils, fpcunit, testregistry, fpjson; Classes, SysUtils, fpcunit, testregistry, fpjson, contnrs;
type type
TMyNull = Class(TJSONNull); TMyNull = Class(TJSONNull);
@ -212,8 +212,14 @@ type
TTestObject = class(TTestJSON) TTestObject = class(TTestJSON)
private private
FJ: TJSONObject;
procedure AppendA;
protected
Procedure Setup; override;
Procedure TearDown; override;
procedure TestAddBoolean(B : Boolean); procedure TestAddBoolean(B : Boolean);
Procedure TestAccessError; Procedure TestAccessError;
Property J : TJSONObject Read FJ;
published published
Procedure TestCreate; Procedure TestCreate;
Procedure TestCreateString; Procedure TestCreateString;
@ -257,6 +263,7 @@ type
Procedure TestFormatNil; Procedure TestFormatNil;
Procedure TestFind; Procedure TestFind;
Procedure TestIfFind; Procedure TestIfFind;
Procedure TestDuplicate;
end; end;
{ TTestJSONPath } { TTestJSONPath }
@ -3060,12 +3067,7 @@ end;
procedure TTestObject.TestCreate; procedure TTestObject.TestCreate;
Var
J : TJSONObject;
begin begin
J:=TJSONObject.Create;
try
TestJSONType(J,jtObject); TestJSONType(J,jtObject);
TestItemCount(J,0); TestItemCount(J,0);
TestJSON(J,'{}'); TestJSON(J,'{}');
@ -3076,9 +3078,6 @@ begin
TestAsQword(J,1,True); TestAsQword(J,1,True);
TestAsString(J,'',True); TestAsString(J,'',True);
TestAsFloat(J,0.0,True); TestAsFloat(J,0.0,True);
finally
FreeAndNil(J);
end;
end; end;
procedure TTestObject.TestAddInteger; procedure TTestObject.TestAddInteger;
@ -3086,12 +3085,7 @@ procedure TTestObject.TestAddInteger;
Const Const
A = 'a'; A = 'a';
Var
J : TJSONObject;
begin begin
J:=TJSonObject.Create;
try
J.Add(A,Integer(0)); J.Add(A,Integer(0));
TestItemCount(J,1); TestItemCount(J,1);
TestJSONType(J[A],jtNumber); TestJSONType(J[A],jtNumber);
@ -3102,9 +3096,6 @@ begin
TestAsInt64(J[A],0); TestAsInt64(J[A],0);
TestAsQword(J[A],0); TestAsQword(J[A],0);
TestJSON(J,'{ "'+A+'" : 0 }'); TestJSON(J,'{ "'+A+'" : 0 }');
finally
FreeAndNil(J);
end;
end; end;
procedure TTestObject.TestAddInt64; procedure TTestObject.TestAddInt64;
@ -3112,12 +3103,7 @@ procedure TTestObject.TestAddInt64;
Const Const
A = 'a'; A = 'a';
Var
J : TJSONObject;
begin begin
J:=TJSonObject.Create;
try
J.Add(A,Int64(0)); J.Add(A,Int64(0));
TestItemCount(J,1); TestItemCount(J,1);
TestJSONType(J[A],jtNumber); TestJSONType(J[A],jtNumber);
@ -3128,9 +3114,6 @@ begin
TestAsInt64(J[A],0); TestAsInt64(J[A],0);
TestAsQword(J[A],0); TestAsQword(J[A],0);
TestJSON(J,'{ "'+A+'" : 0 }'); TestJSON(J,'{ "'+A+'" : 0 }');
finally
FreeAndNil(J);
end;
end; end;
procedure TTestObject.TestAddFloat; procedure TTestObject.TestAddFloat;
@ -3139,13 +3122,10 @@ Const
A = 'a'; A = 'a';
Var Var
J : TJSONObject;
S : String; S : String;
F : TJSONFloat; F : TJSONFloat;
begin begin
F:=1.2; F:=1.2;
J:=TJSonObject.Create;
try
J.Add(A,F); J.Add(A,F);
TestItemCount(J,1); TestItemCount(J,1);
TestJSONType(J[A],jtNumber); TestJSONType(J[A],jtNumber);
@ -3155,9 +3135,18 @@ begin
TestAsFloat(J[A],F); TestAsFloat(J[A],F);
Str(F,S); Str(F,S);
TestJSON(J,'{ "'+a+'" :'+S+' }'); TestJSON(J,'{ "'+a+'" :'+S+' }');
finally
FreeAndNil(J);
end; end;
procedure TTestObject.Setup;
begin
inherited Setup;
FJ:=TJSONObject.Create;
end;
procedure TTestObject.TearDown;
begin
FreeAndNil(FJ);
inherited TearDown;
end; end;
procedure TTestObject.TestAddBoolean(B : Boolean); procedure TTestObject.TestAddBoolean(B : Boolean);
@ -3165,13 +3154,8 @@ procedure TTestObject.TestAddBoolean(B : Boolean);
Const Const
A = 'a'; A = 'a';
Var
J : TJSONObject;
begin begin
B:=True; B:=True;
J:=TJSonObject.Create;
try
J.Add(A,B); J.Add(A,B);
TestItemCount(J,1); TestItemCount(J,1);
TestJSONType(J[A],jtBoolean); TestJSONType(J[A],jtBoolean);
@ -3182,24 +3166,12 @@ begin
TestJSON(J,'{ "'+a+'" : true }') TestJSON(J,'{ "'+a+'" : true }')
else else
TestJSON(J,'{ "'+a+'" : false }'); TestJSON(J,'{ "'+a+'" : false }');
finally
FreeAndNil(J);
end;
end; end;
procedure TTestObject.TestAccessError; procedure TTestObject.TestAccessError;
Var
J : TJSONObject;
begin begin
J:=TJSonObject.Create;
try
J.Strings['NonExist']; J.Strings['NonExist'];
finally
FreeAndNil(J);
end;
end; end;
procedure TTestObject.TestAddBooleanTrue; procedure TTestObject.TestAddBooleanTrue;
@ -3220,13 +3192,10 @@ Const
A = 'a'; A = 'a';
Var Var
J : TJSONObject;
S : String; S : String;
begin begin
S:='A string'; S:='A string';
J:=TJSonObject.Create;
try
J.Add(A,S); J.Add(A,S);
TestItemCount(J,1); TestItemCount(J,1);
TestJSONType(J[a],jtString); TestJSONType(J[a],jtString);
@ -3234,9 +3203,6 @@ begin
TestAsString(J[a],S); TestAsString(J[a],S);
AssertEquals('J.Strings[''a'']="'+S+'"',S,J.Strings[A]); AssertEquals('J.Strings[''a'']="'+S+'"',S,J.Strings[A]);
TestJSON(J,'{ "'+a+'" : "'+StringToJSONString(S)+'" }'); TestJSON(J,'{ "'+a+'" : "'+StringToJSONString(S)+'" }');
finally
FreeAndNil(J);
end;
end; end;
procedure TTestObject.TestAddNull; procedure TTestObject.TestAddNull;
@ -3244,12 +3210,7 @@ procedure TTestObject.TestAddNull;
Const Const
A = 'a'; A = 'a';
Var
J : TJSONObject;
begin begin
J:=TJSonObject.Create;
try
J.Add(a); J.Add(a);
TestItemCount(J,1); TestItemCount(J,1);
TestJSONType(J[a],jtNull); TestJSONType(J[a],jtNull);
@ -3257,9 +3218,6 @@ begin
AssertEquals('J.Nulls[''a'']=True',True,J.Nulls[A]); AssertEquals('J.Nulls[''a'']=True',True,J.Nulls[A]);
TestIsNull(J[a],true); TestIsNull(J[a],true);
TestJSON(J,'{ "'+a+'" : null }'); TestJSON(J,'{ "'+a+'" : null }');
finally
FreeAndNil(J);
end;
end; end;
procedure TTestObject.TestAddObject; procedure TTestObject.TestAddObject;
@ -3270,11 +3228,9 @@ Const
C = 'c'; C = 'c';
Var Var
J,J2 : TJSONObject; J2 : TJSONObject;
begin begin
J:=TJSonObject.Create;
try
J2:=TJSonObject.Create; J2:=TJSonObject.Create;
J2.Add(B,0); J2.Add(B,0);
J2.Add(C,1); J2.Add(C,1);
@ -3290,9 +3246,6 @@ begin
TestAsQword(J.Objects[A][B],0); TestAsQword(J.Objects[A][B],0);
TestAsQword(J.Objects[A][C],1); TestAsQword(J.Objects[A][C],1);
TestJSON(J,'{ "a" : { "b" : 0, "c" : 1 } }'); TestJSON(J,'{ "a" : { "b" : 0, "c" : 1 } }');
finally
FreeAndNil(J);
end;
end; end;
procedure TTestObject.TestAddArray; procedure TTestObject.TestAddArray;
@ -3301,12 +3254,9 @@ Const
A = 'a'; A = 'a';
Var Var
J : TJSONObject;
J2 : TJSONArray; J2 : TJSONArray;
begin begin
J:=TJSONObject.Create;
try
J2:=TJSonArray.Create; J2:=TJSonArray.Create;
J2.Add(0); J2.Add(0);
J2.Add(1); J2.Add(1);
@ -3322,9 +3272,6 @@ begin
TestAsQword(J.Arrays[A][0],0); TestAsQword(J.Arrays[A][0],0);
TestAsQword(J.Arrays[A][1],1); TestAsQword(J.Arrays[A][1],1);
TestJSON(J,'{ "a" : [0, 1] }'); TestJSON(J,'{ "a" : [0, 1] }');
finally
FreeAndNil(J);
end;
end; end;
procedure TTestObject.TestDelete; procedure TTestObject.TestDelete;
@ -3333,12 +3280,7 @@ Const
A = 'a'; A = 'a';
B = 'b'; B = 'b';
Var
J : TJSONObject;
begin begin
J:=TJSonObject.Create;
try
J.Add(A,0); J.Add(A,0);
J.Add(B,1); J.Add(B,1);
TestItemCount(J,2); TestItemCount(J,2);
@ -3349,9 +3291,6 @@ begin
TestItemCount(J,1); TestItemCount(J,1);
J.Delete(0); J.Delete(0);
TestItemCount(J,0); TestItemCount(J,0);
finally
FreeAndNil(J);
end;
end; end;
procedure TTestObject.TestRemove; procedure TTestObject.TestRemove;
@ -3362,12 +3301,9 @@ Const
C = 'c'; C = 'c';
Var Var
J : TJSONObject;
I : TJSONData; I : TJSONData;
begin begin
J:=TJSonObject.Create;
try
J.Add(A,1); J.Add(A,1);
J.Add(B,2); J.Add(B,2);
J.Add(C,3); J.Add(C,3);
@ -3385,20 +3321,15 @@ begin
TestAsInt64(J[c],3); TestAsInt64(J[c],3);
TestAsQword(J[a],1); TestAsQword(J[a],1);
TestAsQword(J[c],3); TestAsQword(J[c],3);
finally
FreeAndNil(J);
end;
end; end;
procedure TTestObject.TestClone; procedure TTestObject.TestClone;
Var Var
J,J2 : TJSONObject; J2 : TJSONObject;
D : TJSONData; D : TJSONData;
begin begin
J:=TJSonObject.Create;
try
J.Add('p1',1); J.Add('p1',1);
J.Add('p2','aloha'); J.Add('p2','aloha');
D:=J.Clone; D:=J.Clone;
@ -3413,30 +3344,26 @@ begin
finally finally
D.Free; D.Free;
end; end;
finally
FreeAndNil(J);
end;
end; end;
procedure TTestObject.TestMyClone; procedure TTestObject.TestMyClone;
Var Var
J : TMyObject;
D : TJSONData; D : TJSONData;
O : TMyObject;
begin begin
J:=TMyObject.Create; D:=Nil;
try O:=TMyObject.Create;
J.Add('p1',1);
J.Add('p2','aloha');
D:=J.Clone;
try try
O.Add('p1',1);
O.Add('p2','aloha');
D:=O.Clone;
TestJSONType(D,jtObject); TestJSONType(D,jtObject);
AssertEquals('Correct class',TMYObject,D.ClassType); AssertEquals('Correct class',TMYObject,D.ClassType);
finally finally
D.Free; D.Free;
end; O.Free;
finally
FreeAndNil(J);
end; end;
end; end;
@ -3447,12 +3374,10 @@ Const
B = 'b'; B = 'b';
Var Var
J : TJSONObject;
JA,JB : TJSONData; JA,JB : TJSONData;
E : TJSONData; E : TJSONData;
begin begin
J:=TJSonObject.Create;
try
J.Add(A,0); J.Add(A,0);
J.Add(B,1); J.Add(B,1);
TestItemCount(J,2); TestItemCount(J,2);
@ -3469,10 +3394,6 @@ begin
AssertSame('Extracted JB',JA,E); AssertSame('Extracted JB',JA,E);
E.Free; E.Free;
TestItemCount(J,0); TestItemCount(J,0);
finally
FreeAndNil(J);
end;
end; end;
procedure TTestObject.TestNonExistingAccessError; procedure TTestObject.TestNonExistingAccessError;
@ -3504,19 +3425,11 @@ end;
procedure TTestObject.TestFormatNil; procedure TTestObject.TestFormatNil;
Var
J : TJSONObject;
begin begin
J:=TJSONObject.Create;
try
J.Add('a',1); J.Add('a',1);
J.Add('b',TJSONObject(Nil)); J.Add('b',TJSONObject(Nil));
TestJSON(J,'{ "a" : 1, "b" : null }'); TestJSON(J,'{ "a" : 1, "b" : null }');
AssertEquals('FormatJSON, single line',J.AsJSON,J.FormatJSON([foSingleLineObject],1)); AssertEquals('FormatJSON, single line',J.AsJSON,J.FormatJSON([foSingleLineObject],1));
finally
J.Free;
end;
end; end;
procedure TTestObject.TestFind; procedure TTestObject.TestFind;
@ -3529,12 +3442,10 @@ Const
C = 'c'; C = 'c';
S3 = 'Yet Another string'; S3 = 'Yet Another string';
Var
J : TJSONObject;
begin begin
J:=TJSONObject.Create([A,S,B,S2,C,S3]); J.Add(A,S);
try J.Add(B,S2);
J.Add(C,S3);
TestJSONType(J,jtObject); TestJSONType(J,jtObject);
TestIsNull(J,False); TestIsNull(J,False);
TestItemCount(J,3); TestItemCount(J,3);
@ -3549,21 +3460,18 @@ begin
AssertEquals('4 Existing exact match, case insensitive',1,J.IndexOfName(B,true)); AssertEquals('4 Existing exact match, case insensitive',1,J.IndexOfName(B,true));
AssertEquals('5 Existing , case sensitive again',2,J.IndexOfName(C)); AssertEquals('5 Existing , case sensitive again',2,J.IndexOfName(C));
AssertEquals('6 Existing case-insensitive match, case insensitive',2,J.IndexOfName(Uppercase(C),true)); AssertEquals('6 Existing case-insensitive match, case insensitive',2,J.IndexOfName(Uppercase(C),true));
finally
FreeAndNil(J);
end;
end; end;
Procedure TTestObject.TestIfFind; Procedure TTestObject.TestIfFind;
Var Var
J: TJSONObject;
B: TJSONBoolean; B: TJSONBoolean;
S: TJSONString; S: TJSONString;
N: TJSONNumber; N: TJSONNumber;
D: TJSONData; D: TJSONData;
begin begin
J:=TJSONObject.Create(['s', 'astring', 'b', true, 'n', 1]); J.Add('s', 'astring');
try J.Add('b', true);
J.Add('n', 1);
TestJSONType(J,jtObject); TestJSONType(J,jtObject);
TestIsNull(J,False); TestIsNull(J,False);
TestItemCount(J,3); TestItemCount(J,3);
@ -3571,9 +3479,19 @@ begin
AssertEquals('string found', true, j.Find('s', S)); AssertEquals('string found', true, j.Find('s', S));
AssertEquals('number found', true, j.Find('n', N)); AssertEquals('number found', true, j.Find('n', N));
AssertEquals('data found', true, j.Find('s', D)); AssertEquals('data found', true, j.Find('s', D));
finally
FreeAndNil(J);
end; end;
procedure TTestObject.AppendA;
begin
J.Add('A','S')
end;
procedure TTestObject.TestDuplicate;
begin
J.Add('A',TJSONObject.Create);
AssertException(EJSON,@AppendA);
end; end;
@ -3583,42 +3501,29 @@ Const
A = 'A'; A = 'A';
S = 'A string'; S = 'A string';
Var
J : TJSONObject;
begin begin
J:=TJSONObject.Create([A,S]); J.Add(A,S);
try
TestJSONType(J,jtObject); TestJSONType(J,jtObject);
TestItemCount(J,1); TestItemCount(J,1);
TestJSONType(J[A],jtString); TestJSONType(J[A],jtString);
TestJSON(J,'{ "A" : "'+S+'" }'); TestJSON(J,'{ "A" : "'+S+'" }');
TestIsNull(J,False); TestIsNull(J,False);
finally
FreeAndNil(J);
end;
end; end;
procedure TTestObject.TestCreateStringUnquoted; procedure TTestObject.TestCreateStringUnquoted;
Const Const
A = 'A'; A = 'A';
S = 'A string'; S = 'A string';
Var
J : TJSONObject;
begin begin
TJSONObject.UnquotedMemberNames:=True; TJSONObject.UnquotedMemberNames:=True;
J:=TJSONObject.Create([A,S]); J.Add(A,S);
try
TestJSONType(J,jtObject); TestJSONType(J,jtObject);
TestItemCount(J,1); TestItemCount(J,1);
TestJSONType(J[A],jtString); TestJSONType(J[A],jtString);
TestJSON(J,'{ A : "'+S+'" }'); TestJSON(J,'{ A : "'+S+'" }');
TestIsNull(J,False); TestIsNull(J,False);
finally
FreeAndNil(J);
end;
end; end;
procedure TTestObject.TestCreatePchar; procedure TTestObject.TestCreatePchar;
@ -3628,18 +3533,18 @@ Const
S = 'A string'; S = 'A string';
Var Var
J : TJSONObject; O : TJSONObject;
begin begin
J:=TJSONObject.Create([A,Pchar(S)]); O:=TJSONObject.Create([A,Pchar(S)]);
try try
TestJSONType(J,jtObject); TestJSONType(O,jtObject);
TestItemCount(J,1); TestItemCount(O,1);
TestJSONType(J[A],jtString); TestJSONType(O[A],jtString);
TestJSON(J,'{ "A" : "'+S+'" }'); TestJSON(O,'{ "A" : "'+S+'" }');
TestIsNull(J,False); TestIsNull(O,False);
finally finally
FreeAndNil(J); FreeAndNil(O);
end; end;
end; end;
@ -3650,19 +3555,19 @@ Const
S = 'A string'; S = 'A string';
Var Var
J : TJSONObject; O : TJSONObject;
begin begin
TJSONObject.UnQuotedMemberNames:=True; TJSONObject.UnQuotedMemberNames:=True;
J:=TJSONObject.Create([A,Pchar(S)]); O:=TJSONObject.Create([A,Pchar(S)]);
try try
TestJSONType(J,jtObject); TestJSONType(O,jtObject);
TestItemCount(J,1); TestItemCount(O,1);
TestJSONType(J[A],jtString); TestJSONType(O[A],jtString);
TestJSON(J,'{ A : "'+S+'" }'); TestJSON(O,'{ A : "'+S+'" }');
TestIsNull(J,False); TestIsNull(O,False);
finally finally
FreeAndNil(J); FreeAndNil(O);
end; end;
end; end;
@ -3675,19 +3580,19 @@ Const
T = 'B string'; T = 'B string';
Var Var
J : TJSONObject; O : TJSONObject;
begin begin
J:=TJSONObject.Create([A,S,B,T]); O:=TJSONObject.Create([A,S,B,T]);
try try
TestJSONType(J,jtObject); TestJSONType(O,jtObject);
TestItemCount(J,2); TestItemCount(O,2);
TestJSONType(J[A],jtString); TestJSONType(O[A],jtString);
TestJSONType(J[B],jtString); TestJSONType(O[B],jtString);
TestJSON(J,'{ "A" : "'+S+'", "B" : "'+T+'" }'); TestJSON(O,'{ "A" : "'+S+'", "B" : "'+T+'" }');
TestIsNull(J,False); TestIsNull(O,False);
finally finally
FreeAndNil(J); FreeAndNil(O);
end; end;
end; end;
@ -3700,20 +3605,20 @@ Const
T = 'B string'; T = 'B string';
Var Var
J : TJSONObject; O : TJSONObject;
begin begin
TJSONData.CompressedJSON:=True; TJSONData.CompressedJSON:=True;
J:=TJSONObject.Create([A,S,B,T]); O:=TJSONObject.Create([A,S,B,T]);
try try
TestJSONType(J,jtObject); TestJSONType(O,jtObject);
TestItemCount(J,2); TestItemCount(O,2);
TestJSONType(J[A],jtString); TestJSONType(O[A],jtString);
TestJSONType(J[B],jtString); TestJSONType(O[B],jtString);
TestJSON(J,'{"A":"'+S+'","B":"'+T+'"}'); TestJSON(O,'{"A":"'+S+'","B":"'+T+'"}');
TestIsNull(J,False); TestIsNull(O,False);
finally finally
FreeAndNil(J); FreeAndNil(O);
end; end;
end; end;
@ -3726,21 +3631,21 @@ Const
T = 'B string'; T = 'B string';
Var Var
J : TJSONObject; O : TJSONObject;
begin begin
TJSONData.CompressedJSON:=True; TJSONData.CompressedJSON:=True;
TJSONObject.UnQuotedMemberNames:=True; TJSONObject.UnQuotedMemberNames:=True;
J:=TJSONObject.Create([A,S,B,T]); O:=TJSONObject.Create([A,S,B,T]);
try try
TestJSONType(J,jtObject); TestJSONType(O,jtObject);
TestItemCount(J,2); TestItemCount(O,2);
TestJSONType(J[A],jtString); TestJSONType(O[A],jtString);
TestJSONType(J[B],jtString); TestJSONType(O[B],jtString);
TestJSON(J,'{A:"'+S+'",B:"'+T+'"}'); TestJSON(O,'{A:"'+S+'",B:"'+T+'"}');
TestIsNull(J,False); TestIsNull(O,False);
finally finally
FreeAndNil(J); FreeAndNil(O);
end; end;
end; end;
@ -3751,17 +3656,17 @@ Const
S = 3; S = 3;
Var Var
J : TJSONObject; O : TJSONObject;
begin begin
J:=TJSONObject.Create([A,S]); O:=TJSONObject.Create([A,S]);
try try
TestJSONType(J,jtObject); TestJSONType(O,jtObject);
TestItemCount(J,1); TestItemCount(O,1);
TestJSONType(J[A],jtNumber); TestJSONType(O[A],jtNumber);
TestJSON(J,'{ "A" : 3 }'); TestJSON(O,'{ "A" : 3 }');
finally finally
FreeAndNil(J); FreeAndNil(O);
end; end;
end; end;
@ -3771,18 +3676,18 @@ Const
S = 3; S = 3;
Var Var
J : TJSONObject; O : TJSONObject;
begin begin
TJSONObject.UnQuotedMemberNames:=True; TJSONObject.UnQuotedMemberNames:=True;
J:=TJSONObject.Create([A,S]); O:=TJSONObject.Create([A,S]);
try try
TestJSONType(J,jtObject); TestJSONType(O,jtObject);
TestItemCount(J,1); TestItemCount(O,1);
TestJSONType(J[A],jtNumber); TestJSONType(O[A],jtNumber);
TestJSON(J,'{ A : 3 }'); TestJSON(O,'{ A : 3 }');
finally finally
FreeAndNil(J); FreeAndNil(O);
end; end;
end; end;
@ -3793,19 +3698,19 @@ Const
S : double = 1.2; S : double = 1.2;
Var Var
J : TJSONObject; O : TJSONObject;
r : String; r : String;
begin begin
J:=TJSONObject.Create([A,S]); O:=TJSONObject.Create([A,S]);
try try
TestJSONType(J,jtObject); TestJSONType(O,jtObject);
TestItemCount(J,1); TestItemCount(O,1);
TestJSONType(J[A],jtNumber); TestJSONType(O[A],jtNumber);
Str(S,R); Str(S,R);
TestJSON(J,'{ "A" :'+R+' }'); TestJSON(O,'{ "A" :'+R+' }');
finally finally
FreeAndNil(J); FreeAndNil(O);
end; end;
end; end;
@ -3815,20 +3720,20 @@ Const
S : double = 1.2; S : double = 1.2;
Var Var
J : TJSONObject; O : TJSONObject;
r : String; r : String;
begin begin
TJSONObject.UnQuotedMemberNames:=True; TJSONObject.UnQuotedMemberNames:=True;
J:=TJSONObject.Create([A,S]); O:=TJSONObject.Create([A,S]);
try try
TestJSONType(J,jtObject); TestJSONType(O,jtObject);
TestItemCount(J,1); TestItemCount(O,1);
TestJSONType(J[A],jtNumber); TestJSONType(O[A],jtNumber);
Str(S,R); Str(S,R);
TestJSON(J,'{ A :'+R+' }'); TestJSON(O,'{ A :'+R+' }');
finally finally
FreeAndNil(J); FreeAndNil(O);
end; end;
end; end;
@ -3839,17 +3744,17 @@ Const
S : Int64 = $FFFFFFFFFFFFF; S : Int64 = $FFFFFFFFFFFFF;
Var Var
J : TJSONObject; O : TJSONObject;
begin begin
J:=TJSONObject.Create([A,S]); O:=TJSONObject.Create([A,S]);
try try
TestJSONType(J,jtObject); TestJSONType(O,jtObject);
TestItemCount(J,1); TestItemCount(O,1);
TestJSONType(J[A],jtNumber); TestJSONType(O[A],jtNumber);
TestJSON(J,'{ "A" : '+IntToStr(S)+' }'); TestJSON(O,'{ "A" : '+IntToStr(S)+' }');
finally finally
FreeAndNil(J); FreeAndNil(O);
end; end;
end; end;
@ -3859,18 +3764,18 @@ Const
S : Int64 = $FFFFFFFFFFFFF; S : Int64 = $FFFFFFFFFFFFF;
Var Var
J : TJSONObject; O : TJSONObject;
begin begin
TJSONObject.UnQuotedMemberNames:=True; TJSONObject.UnQuotedMemberNames:=True;
J:=TJSONObject.Create([A,S]); O:=TJSONObject.Create([A,S]);
try try
TestJSONType(J,jtObject); TestJSONType(O,jtObject);
TestItemCount(J,1); TestItemCount(O,1);
TestJSONType(J[A],jtNumber); TestJSONType(O[A],jtNumber);
TestJSON(J,'{ A : '+IntToStr(S)+' }'); TestJSON(O,'{ A : '+IntToStr(S)+' }');
finally finally
FreeAndNil(J); FreeAndNil(O);
end; end;
end; end;
@ -3881,17 +3786,17 @@ Const
S = True; S = True;
Var Var
J : TJSONObject; O : TJSONObject;
begin begin
J:=TJSONObject.Create([A,S]); O:=TJSONObject.Create([A,S]);
try try
TestJSONType(J,jtObject); TestJSONType(O,jtObject);
TestItemCount(J,1); TestItemCount(O,1);
TestJSONType(J[A],jtBoolean); TestJSONType(O[A],jtBoolean);
TestJSON(J,'{ "A" : true }'); TestJSON(O,'{ "A" : true }');
finally finally
FreeAndNil(J); FreeAndNil(O);
end; end;
end; end;
@ -3901,18 +3806,18 @@ Const
S = True; S = True;
Var Var
J : TJSONObject; O : TJSONObject;
begin begin
TJSONObject.UnQuotedMemberNames:=True; TJSONObject.UnQuotedMemberNames:=True;
J:=TJSONObject.Create([A,S]); O:=TJSONObject.Create([A,S]);
try try
TestJSONType(J,jtObject); TestJSONType(O,jtObject);
TestItemCount(J,1); TestItemCount(O,1);
TestJSONType(J[A],jtBoolean); TestJSONType(O[A],jtBoolean);
TestJSON(J,'{ A : true }'); TestJSON(O,'{ A : true }');
finally finally
FreeAndNil(J); FreeAndNil(O);
end; end;
end; end;
@ -3922,16 +3827,16 @@ Const
A = 'A'; A = 'A';
Var Var
J : TJSONObject; O : TJSONObject;
begin begin
J:=TJSONObject.Create([A,TJSONObject.Create]); O:=TJSONObject.Create([A,TJSONObject.Create]);
try try
TestItemCount(J,1); TestItemCount(O,1);
TestJSONType(J[A],jtObject); TestJSONType(O[A],jtObject);
TestJSON(J,'{ "A" : {} }'); TestJSON(O,'{ "A" : {} }');
finally finally
FreeAndNil(J); FreeAndNil(O);
end; end;
end; end;
@ -3940,17 +3845,17 @@ Const
A = 'A'; A = 'A';
Var Var
J : TJSONObject; O : TJSONObject;
begin begin
TJSONObject.UnQuotedMemberNames:=True; TJSONObject.UnQuotedMemberNames:=True;
J:=TJSONObject.Create([A,TJSONObject.Create]); O:=TJSONObject.Create([A,TJSONObject.Create]);
try try
TestItemCount(J,1); TestItemCount(O,1);
TestJSONType(J[A],jtObject); TestJSONType(O[A],jtObject);
TestJSON(J,'{ A : {} }'); TestJSON(O,'{ A : {} }');
finally finally
FreeAndNil(J); FreeAndNil(O);
end; end;
end; end;
@ -3961,16 +3866,16 @@ Const
S = 'A string'; S = 'A string';
Var Var
J : TJSONObject; O : TJSONObject;
begin begin
J:=TJSONObject.Create([A,TJSONString.Create(S)]); O:=TJSONObject.Create([A,TJSONString.Create(S)]);
try try
TestItemCount(J,1); TestItemCount(O,1);
TestJSONType(J[A],jtString); TestJSONType(O[A],jtString);
TestJSON(J,'{ "A" : "'+S+'" }'); TestJSON(O,'{ "A" : "'+S+'" }');
finally finally
FreeAndNil(J); FreeAndNil(O);
end; end;
end; end;
@ -3981,17 +3886,17 @@ Const
S = 'A string'; S = 'A string';
Var Var
J : TJSONObject; O : TJSONObject;
begin begin
TJSONObject.UnQuotedMemberNames:=True; TJSONObject.UnQuotedMemberNames:=True;
J:=TJSONObject.Create([A,TJSONString.Create(S)]); O:=TJSONObject.Create([A,TJSONString.Create(S)]);
try try
TestItemCount(J,1); TestItemCount(O,1);
TestJSONType(J[A],jtString); TestJSONType(O[A],jtString);
TestJSON(J,'{ A : "'+S+'" }'); TestJSON(O,'{ A : "'+S+'" }');
finally finally
FreeAndNil(J); FreeAndNil(O);
end; end;
end; end;
@ -4001,19 +3906,19 @@ Const
A = 'A'; A = 'A';
Var Var
J : TJSONObject; O : TJSONObject;
O : TObject; OO : TObject;
begin begin
J:=Nil; O:=Nil;
try try
Try Try
O:=TObject.Create; OO:=TObject.Create;
J:=TJSONObject.Create([A,O]); O:=TJSONObject.Create([A,OO]);
Fail('Array constructor accepts only TJSONData'); Fail('Array constructor accepts only TJSONData');
finally finally
FreeAndNil(J);
FreeAndNil(O); FreeAndNil(O);
FreeAndNil(OO);
end; end;
except except
// Should be OK. // Should be OK.
@ -4026,17 +3931,17 @@ Const
A = 'A'; A = 'A';
Var Var
J : TJSONObject; O : TJSONObject;
P : Pointer; P : Pointer;
begin begin
J:=Nil; O:=Nil;
P:=Nil; P:=Nil;
Try Try
J:=TJSONObject.Create([A,P]); O:=TJSONObject.Create([A,P]);
TestJSONType(J[A],jtNull); TestJSONType(O[A],jtNull);
finally finally
FreeAndNil(J); FreeAndNil(O);
end; end;
end; end;
@ -4046,18 +3951,18 @@ Const
A = 'A'; A = 'A';
Var Var
J : TJSONObject; O : TJSONObject;
P : Pointer; P : Pointer;
begin begin
J:=Nil; O:=Nil;
P:=@Self; P:=@Self;
try try
Try Try
J:=TJSONObject.Create([A,P]); O:=TJSONObject.Create([A,P]);
Fail('Array constructor accepts only NIL pointers'); Fail('Array constructor accepts only NIL pointers');
finally finally
FreeAndNil(J); FreeAndNil(O);
end; end;
except except
// Should be OK. // Should be OK.