Icon View Thread

The following is the text of the current message along with any replies.
Messages 1 to 7 of 7 total
Thread Variable Published Property Names in JSON Responses
Thu, Dec 21 2017 11:18 AMPermanent Link

Mark Brooks

Slikware

Avatar

Seasons Greetings All

Has anybody come across an API whose structure remains fixed BUT whose "entity names" are variable?

I have just found one that I need to integrate with and I'm a bit stuffed. I could create many, many versions of my EWB response class to handle the different scenarios, but ideally I'd like one version whose published property names can change at runtime to meet the response format.

The good news is that I know what they'll be called at runtime when I make a request i.e. if I make a specific request then I know what the "entity names" will be in the response.

Make sense?
Mark
Thu, Dec 21 2017 11:55 AMPermanent Link

Matthew Jones

Mark Brooks wrote:

> Has anybody come across an API whose structure remains fixed BUT whose "entity names" are variable?

Look up how to do arrays, and you can use that mechanism.

function LoadProperty(AReader: TReader): Boolean; override;

function TJobWorkItem.LoadProperty(AReader: TReader): Boolean;
var
   szPropertyName : String;
begin
   Result := False;
   szPropertyName := AReader.GetPropertyName;
   if (szPropertyName <> '') then
   begin
       if SameText(szPropertyName, 'material') then
       begin
           Result := True;
           AReader.SkipPropertyName;
           AReader.SkipPropertySeparator;
           LoadArray(AReader);
       end
       else if SameText(szPropertyName, 'plant') then
       begin
           Result := True;
           AReader.SkipPropertyName;
           AReader.SkipPropertySeparator;
           LoadArray(AReader);
       end
       else
       begin
           Result := inherited LoadProperty(AReader);
       end;
   end;
end;

(I've cut out the part here which tells LoadArray where to store the particular array as it doesn't matter for you.

--

Matthew Jones
Thu, Dec 21 2017 1:45 PMPermanent Link

Mark Brooks

Slikware

Avatar

Hi Mathew

Thanks for replying. I use arrays lots, but not sure this helps me. There are a possible 1,000 (ish) different values that I'd need to code for so it would become very unwieldy. What I really need is to be able to specify the "entity name(s)" at the point I instantiate the object.

Cheers
Mark
Fri, Dec 22 2017 3:55 AMPermanent Link

Matthew Jones

Mark Brooks wrote:

> Thanks for replying. I use arrays lots, but not sure this helps me. There are a possible 1,000 (ish) different values that I'd need to code for so it would become very unwieldy. What I really need is to be able to specify the "entity name(s)" at the point I instantiate the object.

How about using the old parser? You just give it the JSON string, and make requests from it. Thus you don't have to have any matching object at all.

Code for the old parser below. You have to expose TokenPos in the parser for it to work. I think I got all this from these forums, but I can dig up the variations if you want this. I'm moving to objects in my code now though.

(I think the alternative would be to take a property, and store it in a dictionary, so you'd see the property "matthew" and store it's value in a string list as .Items['matthew'] := value so you can have whatever you want. (Where the items index would be the variable with the name of course).



--

Matthew Jones


function json_ReadString(szJSONData : String; szItemName : String; szDefault : String) : String;
var
   szName : String;
//    szValue : String;
//    bAddComma : Boolean;
//    nLoop : Integer;
   xParser: TParser;
begin
   Result := szDefault;

   xParser := TParser.Create;
   try
       xParser.Initialize(szJSONData, false);
       xParser.ErrorIfNotSkipToken('{');
       while true do
       begin
           xParser.ErrorIfNotToken(tkString);
           szName := xParser.TokenString;
           xParser.NextToken;
           xParser.ErrorIfNotSkipToken(':');
           if szName = szItemName then
           begin
//                xParser.NextToken;
//                xParser.ErrorIfNotSkipToken(':');
               Result := xParser.TokenString;
               exit;
           end
           else
           begin
               if (xParser.Token = '{') or (xParser.Token = '[')  then
               begin
                 json_SkipNested(xParser);
               end
               else
               begin
                  if (xParser.Token = tkInteger) then
                  begin
                  end
                  else if (xParser.Token = tkSymbol) then
                  begin
                  end
                  else
                  begin
                   xParser.ErrorIfNotToken(tkString);
                  end;
//                    szValue := xParser.TokenString;
                   xParser.NextToken;
//                    if (not xParser.SkipToken(',')) then
//                       Break;
               end;
           end;
           if (not xParser.SkipToken(',')) then
              Break;
       end;
       xParser.ErrorIfNotSkipToken('}');
   finally
       xParser.Free;
   end;
end;
Fri, Dec 22 2017 6:42 AMPermanent Link

Mark Brooks

Slikware

Avatar

Hey Mathew

Thanks for replying. There might be something I can use here. Will play a bit!

Much appreciated

Mark
Fri, Dec 22 2017 1:58 PMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com

Mark,

<< Has anybody come across an API whose structure remains fixed BUT whose "entity names" are variable?

I have just found one that I need to integrate with and I'm a bit stuffed. I could create many, many versions of my EWB response class to handle the different scenarios, but ideally I'd like one version whose published property names can change at runtime to meet the response format. >>

Changing published properties at run-time is a non-starter, so that's out (the compiler actually emits a lot of information about published properties behind the scenes to allow for RTTI, so this information cannot be generated at run-time).

However, EWB's persistent loading functionality ignores any published properties that aren't in the incoming JSON, so you could just create one big "super class" that contains all published properties that may be present in the incoming JSON, and it would work.  The bigger worry is if you need to then persist the class from within your EWB application.  In such a case, the "super class" will be a problem and you'll need to code your own overridden Save method  that handles all of the permutations.

Tim Young
Elevate Software
www.elevatesoft.com
Sat, Dec 23 2017 5:35 AMPermanent Link

Mark Brooks

Slikware

Avatar

Tim Young [Elevate Software] wrote:

>>However, EWB's persistent loading functionality ignores any published properties that aren't in the incoming JSON, >>so you could just create one big "super class" that contains all published properties that may be present in the >>incoming JSON, and it would work.  The bigger worry is if you need to then persist the class from within your EWB >>application.  In such a case, the "super class" will be a problem and you'll need to code your own overridden Save >>method  that handles all of the permutations.

Thanks Tim - that's a workable solution for me - actually I blame the JSON provider because why would you change the names anyway!

Have a great Christmas

Mark
Image