Jump to content
David Schwartz

swagger help needed

Recommended Posts

I'm trying to build a small test bed in Delphi for accessing an internal company API and there's a swagger link published for it. What I want to do is suck in the Swagger definition and use it to build something that lets me query the API in Delphi. I'm not sure what all that requires. I guess most of the time people use some kind of javascript framework for this; I want to use Delphi.

 

I searched around on Google and found this project: https://github.com/marcelojaloto/SwagDoc

 

There's a demo in it named 'GenerateUnitFileForMVCFramework' that lets me put in the Swagger URL and it generates a Delphi unit.

 

It works fine, but there may be a bug in this code in that it duplicates every class and interface definition. I was able to fix that without much trouble in the code generator, but there may be a problem in the part that's parsing the Swagger. (Right now I don't care.)

 

I guess the MVC Framework comes from here: https://github.com/danieleteti/delphimvcframework

 

I'm not exactly sure what to do from here. I need a way to connect to the service with OAuth2, and then make some queries and display the results in a form, like in a TListview.

 

I'm looking for suggestions on how to proceed.

 

Thanks!

 

FWIW, someone here wrote a similar thing that generates C# code from a Swagger URL, and that code looks very similar to the Delphi code that's generated by this SwagDoc tool.

 

Edited by David Schwartz
  • Like 1

Share this post


Link to post

So I've been messing with this stuff all week, and Swagger / OpenAPI seems to be a way of documenting an API, like a DDL for databases.

 

You can build a UI from a Swagger definition fairly easily, but if you need any kind of authentication, it seems problematic. It's ok for basic testing, tho, especially if no auth is needed.

 

Given the derth of "Swagger to ________" code generators, I'm guessing that's not somethign done very frequently. The main one at swagger.io supports a couple dozen languages, but Delphi and Pascal aren't among them. 

 

SwagDoc is the only one I've found so far, and there's only one demo for generating client-side code. It's got a few bugs, and there's a lot more it could do. The basic Swagger test UI that can be generated is fairly nice for an auto-generated script. You can read and display data very easily. It would be nice if the Delphi code that's generated had sufficient code generated to produce a similar result, but I guess that's left as an exercise for the reader.

 

Has anybody here ever approached things from this direction -- using Swagger / OpenAPI to help generate Delphi client-side code that makes REST calls? I'm curious what you may have found and problems you encountered.

 

I know Delphi has tools to call JSON-REST APIs fairly easily. But when there are nearly 100 APIs and many of the objects the APIs return have nested objects, lists, and/or arrays embedded in them, that complicates things quite a bit.

 

Or maybe the guys who defined this API have gone a bit overboard? It's a long way from most relatively small API calls and what this particular API I'm working with includes.

Edited by David Schwartz

Share this post


Link to post

I'v created my own swagger (json) to delphi creator.

It creates some model classes, and a base api client, all the models from swagger can be placed in one file, or every class in a separate file.
Currently only working with Swagger v1 json.


I try to put a version online when i get it working with the v3 specs.


I (we) have written a base json client, which can do several methods of authentication, on top on that, i created a base SwaggerClient, and on top of that you get the generated base client, with al the base api calls following the swagger defintion.

example of calling the SWGParser and DelphiGenerator
(its not 100% ready :), the parses should return an swaggermodel, which would be given to the generator for example).


If you have a swagger.json (v1) then i could try to generate the files for you.

 

procedure TfrmSWGTest.CreateFromSwaggerButton9Click(Sender: TObject);
var
  parser : TSWGParser;
  generator : TSWGDelphiGenerator;
begin
  parser := TSWGParser.Create;
  try
    parser.Parse('C:\MySources\MyCompany\Applicaties\MyApplication\Source\API\Source\MySwagger_File.json');
    generator := TSWGDelphiGenerator.Create;
    try
      generator.APIName := 'MyApplicationAPI';
      generator.FilePrefix := 'MyCompany.';
      generator.TypePrefix := 'MyApplicationAPI';
      generator.ModulSubName := 'DTO';
      generator.HTTPMethodPrefix := '/monitoring';

      generator.ExcludeHTTPMethodName := True;
      generator.IncludeCodeComments := False;

      generator.SingleDTOFile := True;
      generator.Generate(parser, 'C:\MySources\MyCompany\Applicaties\MyApplication\Source\API\Generated');

    finally
      generator.Free;
    end;
  finally
    parser.Free;
  end;
end;

Edited by mvanrijnen

Share this post


Link to post

Thanks, but we're using Swagger V2.0.

 

There are C# tools that do this. One thing that makes that really nice is that C# has some constructs that make the classes far smaller than Delphi for the same stuff. Plus, C# supports "partial" class definitions. I don't know why people are so damned allergic to adding stuff like this to the Delphi language. And they want to know why people think Delphi is regarded as "ancient".... sheesh ... it handles a few common use cases really well, and everything else very poorly.

 

That SwagDoc project has the GenerateUnitFileForMVCFramework that I've been playing with. The author did a great job overall separating different parts of the code, but he didn't really separate the Swagger parser from the code generator. (You call the Generate function and it parses the swagger code.) I've been messing with that and discovered they're independent, and it's possible to work with the parser's output for multi-pass code-gen without having to re-parse anything. So perhaps you could use it to upgrade to Swagger V2.

 

Also, I find that although this code appears to be part of an MVC Framework, it's mainly using parts of Teti's DelphiMVCFramework to leverage code for handling Attribute tags on everything. None of the code being generated is specific to MVC per se, as this approach seems to primarily focus on the various Models the API exposes. The V and C parts are left for the user to fill-in.

 

FWIW, it would be far easier to generate C# code from the Swagger data than Delphi code, b/c there's just far less needed for the same goals.

 

That said, there are several different directions one can go with the generated code. The obvious one is a bunch of data classes and a big class that contains methods that implement the API methods. But in looking at our code, I see there are actually two levels of logic: one is a high-level set of methods that take data conforming to the data classes defined in the Swagger spec and pass them to the API methods. The lower-level one is querying the DB and pulling out data and saving it into lists or arrays of data classes from the Swagger spec. Some people here are implementing that lower-level part using an ORM (Entity Framework Core) and some are just doing direct SQL calls. 

 

So there's an opportunity to generate more code that would simplify reaching different goals. Just something to think about.

 

Edited by David Schwartz

Share this post


Link to post

I also for fun run the C# generator, on the swagger def i'm using, and the generated code is similar to that i generate in Delphi.

You always will have:

- your "data classes", with lists (arrays in my case).

- A big class which implements all the various methods (gets, puts, deletes etc, this will be what your calling from your own client application

- A base client class which does the "lowlevel" http /json etc stuff.

 

C# is not that different from Delphi, i think they are very similar, they have the same designer "Anders Hejlsberg".
It's only that the base code and libs of c# is far more extended then delphi ever will be now days.
 

The partial classes in C# , mainly (as far a i have seen), is handy for seperating forms and there code.

Share this post


Link to post

i mean v2 instead v1 sorry for that.

I just see that the swagger def i use, has went to v3, work to do 🙂

 

Share this post


Link to post
13 hours ago, mvanrijnen said:

C# is not that different from Delphi, i think they are very similar, they have the same designer "Anders Hejlsberg".
It's only that the base code and libs of c# is far more extended then delphi ever will be now days.

I don't know for certain, but I seem to recall there was a language being floated around the time Anders was stolen from Borland that may have turned into C# a year or so later.

 

MS thought C++ had too much irrelevant stuff in it and not enough things for supporting the evolving technologies they were looking at. They had a couple of people on the C++ standards committee who made several proposals that routinely got shot down. 

13 hours ago, mvanrijnen said:

The partial classes in C# , mainly (as far a i have seen), is handy for seperating forms and there code.

"partial" classes are ideal for supporting auto-generated code. They allow you to spread the contents of a given namespace across multiple files. 

 

Personally, I think the whole notion of a "file" as some kind of a meaningful unit of programming has far outlived its useful life. C# has incorporated this in its design, although the programming environment doesn't take much advantage of it. Delphi hasn't even started to move in that direction.

 

The motivation behind this is simple: the IDE should allow us to compose fragments of programs that are saved to a database rather than files, and compose them into larger chunks. Not in contiguous globs of text that we currently call "units" but as little chunks of logic that get glued together as-needed for whatever problem we're solving. 

 

 

Edited by David Schwartz
  • Like 1

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×