I started playing around with the Java API client that Kamil has
generated using -- and it has a different problem before we even come on
to the string vs object debate:


/tmp/out/object/java-okhttp-gson/src/main/java/org/openapitools/client/model/DAGDetail.java:242:
error: cannot find symbol
  public OneOfScheduleInterval getScheduleInterval() {
         ^
  symbol:   class OneOfScheduleInterval
  location: class DAGDetail

Which appears to be a 2 year old, unsolved issue related to the use of
`oneOf` https://github.com/OpenAPITools/openapi-generator/issues/15

If we're talking about generated API clients, should we change our API
to work around this bug?

-a

On May 29 2020, at 5:49 pm, Jarek Potiuk <jarek.pot...@polidea.com> wrote:

>> vs
>> 
>>         conf:
>>           type: object
>>           description: >
>>             JSON object describing additional configuration parameters.
> 
> 
> I looked at the swagger/OpenAPI definition and this one will indeed validate
> that we pass arbitrary object with properties/values.
> 
> It appeared in OpenAPI 3.0 (so very late) and it's called a FreeFormObject
> (https://swagger.io/docs/specification/data-models/dictionaries/)
> but it has a known problem that both Kamil and I describe.
> 
> The automated client generation does not work if this is a "true"
> FreeForm object
> without type specification. One of the benefits of using OpenAPI is
> that you can
> generate client implementation in many languages.
> 
> From what I understand - that single choice prevents our customers to
> use auto-generation in many languages
> = reasons for that explained by Kamil). Here are few examples:
> 
> * Typescript: 
> https://www.gitmemory.com/issue/OpenAPITools/openapi-generator/4119/540506783
> * Java: https://github.com/OpenAPITools/openapi-generator/issues/2037
> * REST client for JIRA (not sure which language) :
> https://community.developer.atlassian.com/t/jira-rest-client-generation-fails-swagger-open-api-generator/36398
> * GO: 
> https://medium.com/real-apis/free-form-objects-with-array-values-72e85c044e4a
> 
> The problem is that the right code cannot be generated for those
> languages for freeForm
> unless you specify "additionalProperties" field which will tell at
> least what types the keys and values
> have. Which we cannot do in our case.
> 
> Unless someone proves that we can generate automatically, usable
> clients in those
> languages automatically this one will be vetoed from my side.
> 
> I think the ease-of-use and the Open API specification we have is to
> make it possible
> for the users to use the API easily. but in this case, by one line
> decision we are basically
> forcing our users to hand-write their whole code
> instead of generating it all because of one "FreeForm" object in the API.
> 
> I don't think there is a lot of empathy to our users if we make this decision.
> To be honest I see it as a bit selfish decision (if what I understand
> is correct).
> 
>> The first one means technically, acording to the spec you can submit `{
>> "conf": "abc" }` -- but that will fail. Where as the second means that
>> both the OpenAPI client, and the automatic validation from Connexion on
>> the server will handle that for us.
> 
> Not fully really because in at least few languages the OpenAPI client
> - and validation -
> will have to be manually written anyway.
> 
>> (With the string case, we would have to JSON deserialize it and check
>> it's an JSON object/ python dict. Nothing else is allowed.)
> 
> Yeah. Now that we know that it's not allowed we know it needs to be 
> dictionary.
> Indeed - we will have to validate that ourselves. There is no
> performance loss though
> more security  (open API has to do it anyway while parsing for "object
> type" and does not
> have to do it for string)
> 
> As I've written before - the only real validation of the data is done
> by the
> DAG reading the values. Nothing prevents the user from sending { "a":
> {"b" : [] } },
> when dag expects {"a": "b"}. We cannot *really* validate the data with
> Open API.
> 
> And I think single `isinstance(json.loads(conf),dict)` is far, far, far
> much easier to write than hand-coding your client class instead of
> generating it.
> 
> As I see it now in this case, the real trade-off we are dealing with
> here is:
> 
> * "should we add this line of code to validate" vs.
> *  "should we make our users suffer and spend extra xx days to write their
>   client libraries instead of generating them".
> 
>> To use your example DagRun class, the signature could become:
>> 
>>   public DagRun(String dagRunId, String executionDate, Object conf);
>> 
>> and then the client can do `gson.toJsonTree(conf).getAsJsonObject()` 
>> internally.
> 
> Actually - It does not work that easily with the dynamic Objects and
> structure of the objects.
> If you want to pass conf as the conf object to the class and get it working
> as you described, you will have to define a separate class for EVERY
> TYPE of conf object
> that you pass to different DAG and know which of the Type object
> should be passed
> to the DagRun constructor.
> 
> This basically means that if you have two DAGs with two different set
> of config parameters you need to define
> different Class for each DAG and know which class shoudl be passed to
> the constructor
> Basically this means that the users will have to develop, recompile
> and release Java client
> every time they add a new DAG that might require some configuration.
> 
> With the string solution the natural thing will be that conf is
> hand"coded" and generated dynamically rather
> then recompiled as a new Java class.
> 
> And you have not shown how you would convert the "client" case I
> mentioned where you specify the conf object
> via command line as string. How would you decide which class to use?
> Based on what? How do you know
> which DAG is which conf class? I think this is a really difficult one
> to pull by the client if they use
> statically typed language like Java.
> 
>> JSON-encoded-string in a JSON api is a "code smell" to me.
> 
> I think we are giving our static language client users much more than
> a "smell" here.
> 

Reply via email to