View Issue Details

IDProjectCategoryView StatusLast Update
0031032FPCPatchpublic2017-01-27 22:02
ReporterBBazAssigned ToMichael Van Canneyt 
PrioritynormalSeverityminorReproducibilityalways
Status resolvedResolutionfixed 
Product Version3.1.1Product Build 
Target Version3.2.0Fixed in Version3.1.1 
Summary0031032: fcl-json - add helpers for examination with branches
DescriptionThis patch adds a new family of helper functions to TJSONObject. It allows to write clean conditional branches from an object, e.g

if MyObjectJson.FindArray('items', MyArray) and not
   MyObjectJson.FindData('disabled', MyData) then
begin
  for i:= 0 to MyArray.Count-1 do {...};
end;
Additional InformationThe patch ass a test but I wasn't able to run it because another test fails previously.
TagsNo tags attached.
Fixed in Revision35343
FPCOldBugId
FPCTarget
Attached Files
  • jsonhelpers.patch (4,534 bytes)
    From 620f024e693c0ec6c28a21d95fb19c8950e1e430 Mon Sep 17 00:00:00 2001
    From: Basile Burg <basile.b@gmx.com>
    Date: Tue, 29 Nov 2016 01:48:03 +0100
    Subject: [PATCH] fcl-json, add helpers for examination with branches
    
    ---
     packages/fcl-json/src/fpjson.pp         | 87 +++++++++++++++++++++++++++++++++
     packages/fcl-json/tests/testjsondata.pp | 23 +++++++++
     2 files changed, 110 insertions(+)
    
    diff --git a/packages/fcl-json/src/fpjson.pp b/packages/fcl-json/src/fpjson.pp
    index 0f76870..ffb8cb6 100644
    --- a/packages/fcl-json/src/fpjson.pp
    +++ b/packages/fcl-json/src/fpjson.pp
    @@ -537,6 +537,12 @@ Type
         Function IndexOfName(const AName: TJSONStringType; CaseInsensitive : Boolean = False): Integer;
         Function Find(Const AName : String) : TJSONData; overload;
         Function Find(Const AName : String; AType : TJSONType) : TJSONData; overload;
    +    function FindData(const key: TJSONStringType; out AValue: TJSONData): boolean;
    +    function FindObject(const key: TJSONStringType; out AValue: TJSONObject): boolean;
    +    function FindArray(const key: TJSONStringType; out AValue: TJSONArray): boolean;
    +    function FindString(const key: TJSONStringType; out AValue: TJSONString): boolean;
    +    function FindBoolean(const key: TJSONStringType; out AValue: TJSONBoolean): boolean;
    +    function FindNumber(const key: TJSONStringType; out AValue: TJSONNumber): boolean;
         Function Get(Const AName : String) : Variant;
         Function Get(Const AName : String; ADefault : TJSONFloat) : TJSONFloat;
         Function Get(Const AName : String; ADefault : Integer) : Integer;
    @@ -3155,6 +3161,87 @@ begin
         Result:=Nil;
     end;
     
    +function TJSONObject.FindData(const key: TJSONStringType; out AValue: TJSONData): boolean;
    +begin
    +  AValue := Find(key);
    +  result := assigned(AValue);
    +end;
    +
    +function TJSONObject.FindObject(const key: TJSONStringType; out AValue: TJSONObject): boolean;
    +var
    +  v: TJSONData;
    +begin
    +  v := Find(key);
    +  if assigned(v) then
    +  begin
    +    result := v.JSONType = jtObject;
    +    if result then
    +      AValue := TJSONObject(v);
    +  end
    +  else
    +    result := false;
    +end;
    +
    +function TJSONObject.FindArray(const key: TJSONStringType; out AValue: TJSONArray): boolean;
    +var
    +  v: TJSONData;
    +begin
    +  v := Find(key);
    +  if assigned(v) then
    +  begin
    +    result := v.JSONType = jtArray;
    +    if result then
    +      AValue := TJSONArray(v);
    +  end
    +  else
    +    result := false;
    +end;
    +
    +function TJSONObject.FindString(const key: TJSONStringType; out AValue: TJSONString): boolean;
    +var
    +  v: TJSONData;
    +begin
    +  v := Find(key);
    +  if assigned(v) then
    +  begin
    +    result := v.JSONType = jtString;
    +    if result then
    +      AValue := TJSONString(v);
    +  end
    +  else
    +    result := false;
    +end;
    +
    +function TJSONObject.FindBoolean(const key: TJSONStringType; out AValue: TJSONBoolean): boolean;
    +var
    +  v: TJSONData;
    +begin
    +  v := Find(key);
    +  if assigned(v) then
    +  begin
    +    result := v.JSONType = jtBoolean;
    +    if result then
    +      AValue := TJSONBoolean(v);
    +  end
    +  else
    +    result := false;
    +end;
    +
    +function TJSONObject.FindNumber(const key: TJSONStringType; out AValue: TJSONNumber): boolean;
    +var
    +  v: TJSONData;
    +begin
    +  v := Find(key);
    +  if assigned(v) then
    +  begin
    +    result := v.JSONType = jtNumber;
    +    if result then
    +      AValue := TJSONNumber(v);
    +  end
    +  else
    +    result := false;
    +end;
    +
     initialization
       // Need to force initialization;
       TJSONData.DetermineElementSeparators;
    diff --git a/packages/fcl-json/tests/testjsondata.pp b/packages/fcl-json/tests/testjsondata.pp
    index f8c2a4d..8b768b2 100644
    --- a/packages/fcl-json/tests/testjsondata.pp
    +++ b/packages/fcl-json/tests/testjsondata.pp
    @@ -256,6 +256,7 @@ type
         Procedure TestFormat;
         Procedure TestFormatNil;
         Procedure TestFind;
    +    Procedure TestIfFind;
       end;
     
       { TTestJSONPath }
    @@ -3553,6 +3554,28 @@ begin
       end;
     end;
     
    +Procedure TTestObject.TestIfFind;
    +Var
    +  J: TJSONObject;
    +  B: TJSONBoolean;
    +  S: TJSONString;
    +  N: TJSONNumber;
    +  D: TJSONData;
    +begin
    +  J:=TJSONObject.Create(['s', 'astring', 'b', true, 'n', 1]);
    +  try
    +    TestJSONType(J,jtObject);
    +    TestIsNull(J,False);
    +    TestItemCount(J,3);
    +    AssertEquals('boolean not found', true, j.FindBoolean('b', B));
    +    AssertEquals('string not found', true, j.FindString('s', S));
    +    AssertEquals('number not found', true, j.FindNumber('n', N));
    +    AssertEquals('data not found', true, j.FindData('s', D));
    +  finally
    +    FreeAndNil(J);
    +  end;
    +end;
    +
     
     procedure TTestObject.TestCreateString;
     
    -- 
    2.1.4
    
    
    jsonhelpers.patch (4,534 bytes)

Activities

BBaz

2016-11-29 01:59

reporter  

jsonhelpers.patch (4,534 bytes)
From 620f024e693c0ec6c28a21d95fb19c8950e1e430 Mon Sep 17 00:00:00 2001
From: Basile Burg <basile.b@gmx.com>
Date: Tue, 29 Nov 2016 01:48:03 +0100
Subject: [PATCH] fcl-json, add helpers for examination with branches

---
 packages/fcl-json/src/fpjson.pp         | 87 +++++++++++++++++++++++++++++++++
 packages/fcl-json/tests/testjsondata.pp | 23 +++++++++
 2 files changed, 110 insertions(+)

diff --git a/packages/fcl-json/src/fpjson.pp b/packages/fcl-json/src/fpjson.pp
index 0f76870..ffb8cb6 100644
--- a/packages/fcl-json/src/fpjson.pp
+++ b/packages/fcl-json/src/fpjson.pp
@@ -537,6 +537,12 @@ Type
     Function IndexOfName(const AName: TJSONStringType; CaseInsensitive : Boolean = False): Integer;
     Function Find(Const AName : String) : TJSONData; overload;
     Function Find(Const AName : String; AType : TJSONType) : TJSONData; overload;
+    function FindData(const key: TJSONStringType; out AValue: TJSONData): boolean;
+    function FindObject(const key: TJSONStringType; out AValue: TJSONObject): boolean;
+    function FindArray(const key: TJSONStringType; out AValue: TJSONArray): boolean;
+    function FindString(const key: TJSONStringType; out AValue: TJSONString): boolean;
+    function FindBoolean(const key: TJSONStringType; out AValue: TJSONBoolean): boolean;
+    function FindNumber(const key: TJSONStringType; out AValue: TJSONNumber): boolean;
     Function Get(Const AName : String) : Variant;
     Function Get(Const AName : String; ADefault : TJSONFloat) : TJSONFloat;
     Function Get(Const AName : String; ADefault : Integer) : Integer;
@@ -3155,6 +3161,87 @@ begin
     Result:=Nil;
 end;
 
+function TJSONObject.FindData(const key: TJSONStringType; out AValue: TJSONData): boolean;
+begin
+  AValue := Find(key);
+  result := assigned(AValue);
+end;
+
+function TJSONObject.FindObject(const key: TJSONStringType; out AValue: TJSONObject): boolean;
+var
+  v: TJSONData;
+begin
+  v := Find(key);
+  if assigned(v) then
+  begin
+    result := v.JSONType = jtObject;
+    if result then
+      AValue := TJSONObject(v);
+  end
+  else
+    result := false;
+end;
+
+function TJSONObject.FindArray(const key: TJSONStringType; out AValue: TJSONArray): boolean;
+var
+  v: TJSONData;
+begin
+  v := Find(key);
+  if assigned(v) then
+  begin
+    result := v.JSONType = jtArray;
+    if result then
+      AValue := TJSONArray(v);
+  end
+  else
+    result := false;
+end;
+
+function TJSONObject.FindString(const key: TJSONStringType; out AValue: TJSONString): boolean;
+var
+  v: TJSONData;
+begin
+  v := Find(key);
+  if assigned(v) then
+  begin
+    result := v.JSONType = jtString;
+    if result then
+      AValue := TJSONString(v);
+  end
+  else
+    result := false;
+end;
+
+function TJSONObject.FindBoolean(const key: TJSONStringType; out AValue: TJSONBoolean): boolean;
+var
+  v: TJSONData;
+begin
+  v := Find(key);
+  if assigned(v) then
+  begin
+    result := v.JSONType = jtBoolean;
+    if result then
+      AValue := TJSONBoolean(v);
+  end
+  else
+    result := false;
+end;
+
+function TJSONObject.FindNumber(const key: TJSONStringType; out AValue: TJSONNumber): boolean;
+var
+  v: TJSONData;
+begin
+  v := Find(key);
+  if assigned(v) then
+  begin
+    result := v.JSONType = jtNumber;
+    if result then
+      AValue := TJSONNumber(v);
+  end
+  else
+    result := false;
+end;
+
 initialization
   // Need to force initialization;
   TJSONData.DetermineElementSeparators;
diff --git a/packages/fcl-json/tests/testjsondata.pp b/packages/fcl-json/tests/testjsondata.pp
index f8c2a4d..8b768b2 100644
--- a/packages/fcl-json/tests/testjsondata.pp
+++ b/packages/fcl-json/tests/testjsondata.pp
@@ -256,6 +256,7 @@ type
     Procedure TestFormat;
     Procedure TestFormatNil;
     Procedure TestFind;
+    Procedure TestIfFind;
   end;
 
   { TTestJSONPath }
@@ -3553,6 +3554,28 @@ begin
   end;
 end;
 
+Procedure TTestObject.TestIfFind;
+Var
+  J: TJSONObject;
+  B: TJSONBoolean;
+  S: TJSONString;
+  N: TJSONNumber;
+  D: TJSONData;
+begin
+  J:=TJSONObject.Create(['s', 'astring', 'b', true, 'n', 1]);
+  try
+    TestJSONType(J,jtObject);
+    TestIsNull(J,False);
+    TestItemCount(J,3);
+    AssertEquals('boolean not found', true, j.FindBoolean('b', B));
+    AssertEquals('string not found', true, j.FindString('s', S));
+    AssertEquals('number not found', true, j.FindNumber('n', N));
+    AssertEquals('data not found', true, j.FindData('s', D));
+  finally
+    FreeAndNil(J);
+  end;
+end;
+
 
 procedure TTestObject.TestCreateString;
 
-- 
2.1.4

jsonhelpers.patch (4,534 bytes)

Luiz Americo

2016-11-29 03:15

developer   ~0096370

Some notes:

- Not sure if it belongs to core fcl-json
- Is possible to overload Find methods with different signatures. Such implementation can be seen at https://github.com/blikblum/luipack/blob/master/luicomponents/luijsonhelpers.pas Feel free to copy if deems appropriate

Michael Van Canneyt

2017-01-27 22:02

administrator   ~0097753

Applied, but changed it to an overloaded version of Find().
Many thanks for the patch.

Issue History

Date Modified Username Field Change
2016-11-29 01:59 BBaz New Issue
2016-11-29 01:59 BBaz File Added: jsonhelpers.patch
2016-11-29 03:15 Luiz Americo Note Added: 0096370
2016-12-01 16:14 Michael Van Canneyt Assigned To => Michael Van Canneyt
2016-12-01 16:14 Michael Van Canneyt Status new => assigned
2017-01-27 22:02 Michael Van Canneyt Fixed in Revision => 35343
2017-01-27 22:02 Michael Van Canneyt Note Added: 0097753
2017-01-27 22:02 Michael Van Canneyt Status assigned => resolved
2017-01-27 22:02 Michael Van Canneyt Fixed in Version => 3.1.1
2017-01-27 22:02 Michael Van Canneyt Resolution open => fixed
2017-01-27 22:02 Michael Van Canneyt Target Version => 3.2.0