Icon View Thread

The following is the text of the current message along with any replies.
Messages 1 to 7 of 7 total
Thread TParser
Thu, May 17 2012 10:43 AMPermanent Link

Mark Brooks

Slikware

Avatar

I am using TParser with a great degree of success in order to traverse JSON returned from a REST API. There does appear to be one issue, however, whereby TParser does not cope successfully with blank values in JSON name-value pairs. This causes it to not recognise the end of the value and continue into the start of the next name. The following would therefore cause an issue:

name=""

Mark
Thu, May 17 2012 1:49 PMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com

Mark,

<< I am using TParser with a great degree of success in order to traverse
JSON returned from a REST API. There does appear to be one issue, however,
whereby TParser does not cope successfully with blank values in JSON
name-value pairs. This causes it to not recognise the end of the value and
continue into the start of the next name. The following would therefore
cause an issue: >>

Could you give me the complete JSON that you're using/receiving ?  Also,
what is the error message that you're seeing ?

Thanks,

Tim Young
Elevate Software
www.elevatesoft.com
Fri, May 18 2012 4:44 AMPermanent Link

Mark Brooks

Slikware

Avatar

>>Could you give me the complete JSON that you're using/receiving ?  Also,
>>what is the error message that you're seeing ?

JSON looks like this:

{"email":"","avatarLink":"","id":127,"name":"Mark_Brooks","privateGroupId":130,"sysAdmin":false,"userAdmin":false,"userName":"MBrooks","workspaceAdmin":false}

I don't get an error, but rather the TParser seems not to handle the name-value pairs where the value is blank ("") such that subsequent names and values get screwed up.

Cheers
Mark
Mon, May 21 2012 8:43 PMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com

Mark,

<< I don't get an error, but rather the TParser seems not to handle the
name-value pairs where the value is blank ("") such that subsequent names
and values get screwed up. >>

In that case, what is the Object Pascal code that you're using with TParser
?  That is most likely where there's an issue.  The TParser, by itself, just
handles the tokenizing.

Thanks,

Tim Young
Elevate Software
www.elevatesoft.com
Tue, May 22 2012 6:17 AMPermanent Link

Mark Brooks

Slikware

Avatar

>>In that case, what is the Object Pascal code that you're using with TParser

TOP LEVEL:

procedure TCastrumUserCollection.LoadFromJSON(const AJSONStr: string);
var
 P: TParser;
 NewUser: TCastrumUser;
begin
 Clear;
 P := TParser.Create;
 try   

   // Load the JSON

   P.Initialize(AJSONStr);

   // Skip past the array (users) opening section

   P.ErrorIfNotSkipToken('{');
   P.ErrorIfNotSkipString('users');
   P.ErrorIfNotSkipToken(':');
   P.ErrorIfNotSkipToken('[');

   // Check there is at least one array element (user)

   if P.CheckToken('{') then
     while True do
       begin     
         
         // Allocate a new user

         NewUser := TCastrumUser.Create;
         try
           NewUser.LoadFromParser(P);
         except    
           NewUser.Free;
           raise;
         end;
         fUserList.Add(NewUser);
         
         // Skip past the array element (user) closing brace

         P.ErrorIfNotSkipToken('}');

         // If there's no more commas then this was the last array element (user)

         if not P.SkipToken(',') then
           break;
       end;
   
   // Skip past the array (users) closing section
   
   P.ErrorIfNotSkipToken(']');
 
 finally
   P.Free;
 end;
end;

WHICH DROPS INTO:

procedure TCastrumUser.LoadFromParser(const AParser: TParser);
var
 NVPName: string;
 NVPValue: string;
begin

 // Skip past the opening brace
 
 AParser.ErrorIfNotSkipToken('{');
 
 // Extract the NVPs
 
 while True do
   begin
 
     // Get the NVP name
 
     AParser.ErrorIfNotToken(tkString);
     NVPName := AParser.TokenString;
     AParser.NextToken;
 
     // Get the NVP value
 
     AParser.ErrorIfNotSkipToken(':');
     NVPValue := AParser.TokenString;
     AParser.NextToken;

     // Check the NVP and apply it to the user
 
     if NVPName = 'id' then
       fId := StrToInt(NVPValue)
     else if NVPName = 'name' then
       fName := NVPValue
     else if NVPName = 'userName' then
       fUserName := NVPValue
     else if NVPName = 'password' then
       fPassword := NVPValue
     else if NVPName = 'sysAdmin' then
       fSysAdmin := StrToBool(NVPValue)
     else if NVPName = 'userAdmin' then
       fUserAdmin := StrToBool(NVPValue)
     else if NVPName = 'workspaceAdmin' then
       fWorkspaceAdmin := StrToBool(NVPValue)
     else if NVPName = 'avatarLink' then
       fAvatarLink := CastrumStripEscapes(NVPValue)
     else if NVPName = 'department' then
       fDepartment := NVPValue
     else if NVPName = 'company' then
       fCompany := NVPValue
     else if NVPName = 'email' then
       fEmail := NVPValue
     else if NVPName = 'phone' then
       fPhone := NVPValue
     else if NVPName = 'mobile' then
       fMobile := NVPValue
     else if NVPName = 'netphone' then
       fNetPhone := NVPValue
     else if NVPName = 'address1' then
       fAddress1 := NVPValue
     else if NVPName = 'address2' then
       fAddress2 := NVPValue
     else if NVPName = 'address3' then
       fAddress3 := NVPValue
     else if NVPName = 'postcode' then
       fPostCode := NVPValue;
 
     // If there are no more commas then this was the last NVP for the user
 
     if not AParser.SkipToken(',') then
       break;
   end;
end;
Tue, May 22 2012 12:58 PMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com

Mark,

I used your LoadFromParser code like this:

type

  TForm1 = class(TForm)
     ParseButton: TButton;
     Memo1: TMemo;
     procedure ParseButtonClick(Sender: TObject);
  private
     procedure LoadUserFromParser(const AParser: TParser);
  public
     { Public declarations }
  end;

var
  Form1: TForm1;

implementation

uses WebHTTP;

procedure TForm1.ParseButtonClick(Sender: TObject);
var
 P: TParser;
begin
 P := TParser.Create;
 try

   // Load the JSON

   P.Initialize(Memo1.Lines.Text);

   // Skip past the array (users) opening section

{    P.ErrorIfNotSkipToken('{');
   P.ErrorIfNotSkipString('users');
   P.ErrorIfNotSkipToken(':');
   P.ErrorIfNotSkipToken('[');}

   // Check there is at least one array element (user)

   if P.CheckToken('{') then
     while True do
       begin

         // Allocate a new user

         LoadUserFromParser(P);

         // Skip past the array element (user) closing brace

         P.ErrorIfNotSkipToken('}');

         // If there's no more commas then this was the last array element
(user)

         if not P.SkipToken(',') then
           break;
       end;

   // Skip past the array (users) closing section

//    P.ErrorIfNotSkipToken(']');

 finally
   P.Free;
 end;
end;

procedure TForm1.LoadUserFromParser(const AParser: TParser);
var
 NVPName: string;
 NVPValue: string;
begin

 // Skip past the opening brace

 AParser.ErrorIfNotSkipToken('{');

 // Extract the NVPs

 while True do
   begin

     // Get the NVP name

     AParser.ErrorIfNotToken(tkString);
     NVPName := AParser.TokenString;
     AParser.NextToken;

     // Get the NVP value

     AParser.ErrorIfNotSkipToken(':');
     NVPValue := AParser.TokenString;
     AParser.NextToken;

     LogOutput(NVPName+': '+NVPValue);  // Log to messages view in the IDE
(local web server must be started)

     // If there are no more commas then this was the last NVP for the user

     if not AParser.SkipToken(',') then
       break;
   end;
end;

against this JSON:

{"email":"","avatarLink":"","id":127,"name":"Mark_Brooks","privateGroupId":130,"sysAdmin":false,"userAdmin":false,"userName":"MBrooks","workspaceAdmin":false}

and it works fine here.

If you have any other questions, please let me know.

Tim Young
Elevate Software
www.elevatesoft.com
Tue, May 22 2012 4:32 PMPermanent Link

Mark Brooks

Slikware

Avatar

>>Mark,
>>
>>I used your LoadFromParser code like this:
>>
>>(see above)
>>
>>against this JSON:
>>
>>
>>{"email":"","avatarLink":"","id":127,"name":"Mark_Brooks","privateGroupId":130,"sysAdmin":false,"userAdmin":false,"userName":"MBrooks","workspaceAdmin":false}
>>
>>and it works fine here.
>>
>>If you have any other questions, please let me know.

Tim,
Out of office (Frown until Friday.
Will try then.
Thanks for testing your end.
Mark
Image