Modeling List of Maps in openapi - java

I need to generate object from *.yaml definitions file. My end goal is generated POJO like in example below:
public class MyGeneratedPojo {
private List<Map<String, MyInternalObject>> internalProperties;
}
I know that I could use additionalProperties in order to model the map. Or I could do something like this:
MyGeneratedPojo:
properties:
type: array
items:
$ref: '#/.../MyInternalMapDefinition'
MyInternalMapDefinition:
type: object
additionalProperties:
type: array
items:
$ref: '#/.../MyInternalMapDefinition'
What I don't like is this "MyInternalMapDefinition" definition. Is there anyway to define/model it as part of "MyGeneratedPojo"

What I don't like is this "MyInternalMapDefinition" definition. Is there anyway to define/model it as part of "MyGeneratedPojo"
You can inline the inner schema:
MyGeneratedPojo:
type: object
properties:
internalProperties:
type: array # List<...>
items:
type: object # Map<String, MyInternalObject>
additionalProperties:
$ref: '#/components/schemas/MyInternalObject'

Related

Using OpenApi codegen for model generation, unable to make HashMap<String, HashMap<String, String>> (Spring, Java)

Within my .yaml file, I have this:
components:
schemas:
InformationObject:
outsideInformationStructure:
description: Outer structure to store all information.
schema:
$ref: "#/components/schemas/InsideInformationStructure"
InsideInformationStructure:
properties:
firstField:
type: string
description: The first field that exists inside the data structure.
secondField:
type: string
description: The second field that exists inside the data structure.
I want my data structure to look like HashMap<String, HashMap<String, String>>. Would this achieve that goal or am I missing something? I'm unsure of how to verify what I have.

openapi-generator-maven-plugin (Java) does not handle allOf properly

With org.openapitools:openapi-generator-maven-plugin, I have noticed that using allOf composed of multiple objects in a response does not generate a class combining these multiple objects. Instead it uses the first class defined in the allOf section.
Here is a minimal example (openapi.yaml) :
openapi: 3.0.0
info:
title: Test
version: v1
paths:
/test:
get:
operationId: get
responses:
'200':
description: Get
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/A'
- $ref: '#/components/schemas/B'
components:
schemas:
A:
type: object
properties:
attA:
type: string
B:
type: object
properties:
attB:
type: integer
When generating the classes in Java via :
mvn org.openapitools:openapi-generator-maven-plugin:5.2.0:generate \
-Dopenapi.generator.maven.plugin.inputSpec=openapi.yaml \
-Dopenapi.generator.maven.plugin.generatorName=java
It shows a warning:
[WARNING] allOf with multiple schemas defined. Using only the first one: A
As expected, it generates classes A and B. But, when calling get(), the value returned by the call is of type A:
DefaultApi api = new DefaultApi();
A a = api.get();
Instead, I would have expected a composite object containing A and B properties (attA and attB), like this (result from https://editor.swagger.io/):
I have created an issue on GitHub, but hopefully someone here may have had the same issue and managed to fix it.
Also, I can't modify the openapi.yaml file because it's an OpenAPI spec provided by an API I have to call, so modifying it would make no sense and will make it so difficult to manage if their OpenAPI spec change over time.

Swagger: Extract common generated implementation

I'm using SpringBoot + Swagger (OpenApi3) + Java for my application. I use the Swagger documentation to import the API into API Gateway.
I have a couple of Java models that both have the following field: List<MyOwnObject> objectList.
When transformed by swagger, I get my models transformed with the same definition for the field:
model1:
type: object
properties:
... // other properties here
objectList:
type: array
items:
$ref: #/components/schemas/MyOwnObject
model2:
type: object
properties:
... // other properties here
objectList:
type: array
items:
$ref: #/components/schemas/MyOwnObject
Now, because of a "feature" in API Gateway, I need to extract these arrays definitions into a single one, referenced in the two models, but I'm not able to find a way to remodel my POJOs to accomplish it.
I require an output similar to this:
model1:
type: object
properties:
... // other properties here
objectList:
$ref: #/components/schemas/commonArray
model2:
type: object
properties:
... // other properties here
objectList:
$ref: #/components/schemas/commonArray
commonArray:
type: array
items:
$ref: #/components/schemas/MyOwnObject
What have I tried
I created a new POJO, containing the list variable. This works, but given that we are adding an extra variable, this affects a current-in-production API schema, which we prefer not to modify.
I created a new POJO extending from ArrayList<MyOwnObject>. During generation, Swagger replaces the new object for the same array schema, leaving the output equal to the original.
I've played with the #Schema and #ArraySchema Swagger annotations without luck.
Do you guys have any idea on how to solve this issue? Is it even possible to accomplish?
Thanks!

How do you have the maven swagger codegen plugin generate Java classes using inheritance?

In our swagger.yaml file, we have a definition Cat that uses allOf to include all properties of Pet.
Cat:
allOf:
- $ref: '#/definitions/Pet'
- type: object
properties:
# ...
The expectation is that when generating Java sources, we get
public class Cat extends Pet {
This works when using the Swagger Editor.
When using swagger-codegen-maven-plugin with no configOptions set, we get the following:
public class Cat {
Cat implements all of Pet's properties itself, instead of extending it.
How do you tell the swagger-codegen-maven-plugin to use Java with inheritance (i.e. extends)? (We tried both spring and java as languages.)
Here's a sample swagger.yaml file:
swagger: '2.0'
info:
version: 1.0.0
title: simple inheritance
tags:
- name: "pet"
paths:
/cat:
put:
tags:
- "pet"
operationId: "updateCat"
consumes:
- "application/json"
parameters:
- in: "body"
name: "body"
required: true
schema:
$ref: "#/definitions/Cat"
responses:
200:
description: Nada
definitions:
Pet:
type: "object"
required:
- "name"
properties:
name:
type: "string"
example: "doggie"
Cat:
allOf:
- $ref: '#/definitions/Pet'
- type: object
properties:
huntingSkill:
type: string
required:
- huntingSkill
As pointed out on github by chiochuan, the workaround is to add
discriminator: "type"
to the parent's definition to make the Java child classes extend it.
definitions:
Pet:
type: "object"
discriminator: "type"
required:
- "name"
properties:
name:
type: "string"
example: "doggie"
It's a bit strange as the OpenAPI Specification Version 2.0 state that the discriminator Fixed Field must reference a property from the same schema, and that it must be a required property, both of which isn't the case - but it works, at least as of today. :)

SWAGGER 2 Inheritance for Request and Response Objects from same Base Object

In my Spring API designed with Swagger 2.0, I'm trying to create Inheritance using swagger. I want to create a base object, which will have common properties for both Request and Response objects. I tried to do it like the example below:
CategoryResponse:
allOf:
- $ref: '#/definitions/Category'
- type: object
properties:
id:
type: integer
example: '1'
CategoryRequest:
type: object
allOf:
- $ref: '#/definitions/Category'
Category:
discriminator: nameCategory
type: object
properties:
nameCategory:
type: string
example: Games
The problem is that I get a Bad Request error when trying to POST or PUT a new CategoryRequest object. It doesn't even gets to the API Controller, so I guess the problem might in the model definition above. I tried many variations, but none of them worked. However, when I try to GET the list of categories, or one category by id, i'm able to do so (My CategoryResponse is working and extending Category fine).
Does anybody knows the correct way of creating this structure using inheritance of a common base model, both for Request and Response objects?
Thanks in advance!
id looks like an auto-generated and read-only property. In that case you don't need inheritance - you can use a single Category schema and mark id as readOnly: true.
Category:
type: object
properties:
nameCategory:
type: string
example: Games
id:
type: integer
readOnly: true # <-----
example: 1
From the OpenAPI Specification:
readOnly
Declares the property as "read only". This means that it MAY be sent as part of a response but MUST NOT be sent as part of the request.

Categories

Resources