Migration from v1 to v2
This document contains all the breaking changes and migration guidelines for adapting your code to the new version.
Using preferred IDs over anonymous IDs
If you use allOf, and properties need to be merged, Modelina is now using preferred IDs over anonymous IDs. That means if a property has an id/title other than anonymous_schema in one of the schemas in a allOf, it will use the non-anonymous id/title.
Example:
1channels: 2 pet: 3 publish: 4 message: 5 oneOf: 6 - $ref: '#/components/messages/Dog' 7 - $ref: '#/components/messages/Cat' 8components: 9 messages: 10 Dog: 11 payload: 12 title: Dog 13 allOf: 14 - $ref: '#/components/schemas/CloudEvent' 15 - type: object 16 properties: 17 type: 18 title: DogType 19 const: Dog 20 Cat: 21 payload: 22 title: Cat 23 allOf: 24 - $ref: '#/components/schemas/CloudEvent' 25 - type: object 26 properties: 27 type: 28 title: CatType 29 const: Cat 30 schemas: 31 CloudEvent: 32 type: object 33 properties: 34 type: 35 type: string 36 required: 37 - type
The type property in the CloudEvent schema will in this case have an anonymous_schema id. If another schema in the allOf list has the same property and an id other than anonymous_schema, it will now use that id. Meaning, in this example, it will be DogType and CatType.
Accurate array types
For JSON Schema inputs (indirectly for AsyncAPI and OpenAPI), additionalItems
was applied to regular array types, when it should only be applied for tuples.
This means that a schema such as:
"tags": {
"type": "array",
"items": {
"$ref": "http://asyncapi.com/definitions/2.6.0/tag.json"
},
"additionalItems": true
},
Would generate a type such as, in TypeScript:
private _tags?: (Tag | any)[];
Where it now generates:
private _tags?: Tag[];
Creates union type for operation message oneOf
In the example above, where operation.message.oneOf
is set, Modelina will now generate a union type for it. Previously, Modelina ignored this union type, and only generated models for the content of operation.message.oneOf
. In the example above, that meant models for Dog
and Cat
. Now, Modelina will generate a union type of Pet
in addition to Dog
and Cat
.
Constraining models with then and else
In v1, required
properties defined within then
or else
(in JSON Schema input variants) would be directly applied to the encapsulating model, meaning it would be as if the if
section is always true or false, depending on whether it's defined within then
or else
respectfully.
In v2, required
properties are no longer applied, but the rest of the structure is still.
Constant values
Constant values are now supported.
1type: object 2properties: 3 country: 4 const: 'United States of America'
The country
property will not have a setter and will automatically be initialized.
Discriminator
Discriminator is now supported.
1schemas: 2 Pet: 3 type: object 4 discriminator: petType 5 properties: 6 petType: 7 type: string 8 name: 9 type: string 10 required: 11 - petType 12 - name 13 Cat: 14 allOf: 15 - $ref: '#/components/schemas/Pet' 16 - type: object 17 properties: 18 petType: 19 const: Cat 20 Dog: 21 allOf: 22 - $ref: '#/components/schemas/Pet' 23 - type: object 24 properties: 25 petType: 26 const: Dog
This example will generate a model for Cat
and Dog
where PetType
is a shared enum that contains two values (Cat
and Dog
). PetType
will not have a setter, and will automatically be initialized.
Optional properties in Kotlin
In Kotlin, if the property is not required
in JSON Schema, it will be nullable with the default value null
.
1Response: 2 type: object 3 properties: 4 result: 5 type: string 6 message: 7 type: string 8 required: 9 - result 10 additionalProperties: false
will generate:
1data class Response( 2 val result: String, 3 val message: String? = null 4)
Optional properties in Java
In Java, if the property is not required
in JSON Schema, it should use nullable types instead of primitive.
1Response: 2 type: object 3 properties: 4 result: 5 type: number 6 message: 7 type: number 8 required: 9 - result 10 additionalProperties: false
Will now generate:
1public class Response { 2 private double result; 3 private Double message; 4 5 public double getResult() { return this.result; } 6 public void setResult(double result) { this.result = result; } 7 8 public Double getMessage() { return this.message; } 9 public void setMessage(Double message) { this.message = message; } 10}
Interface for objects in oneOf for Java
In Java, if a oneOf includes objects, there will be created an interface. All the classes that are part of the oneOf, implements the interface. The Jackson preset includes support for unions by setting @JsonTypeInfo and @JsonSubTypes annotations.
1components: 2 messages: 3 Vehicle: 4 payload: 5 title: Vehicle 6 type: object 7 discriminator: vehicleType 8 properties: 9 vehicleType: 10 title: VehicleType 11 type: string 12 required: 13 - vehicleType 14 oneOf: 15 - $ref: '#/components/schemas/Car' 16 - $ref: '#/components/schemas/Truck' 17 schemas: 18 Car: 19 type: object 20 properties: 21 vehicleType: 22 const: Car 23 Truck: 24 type: object 25 properties: 26 vehicleType: 27 const: Truck
will generate
1@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.EXISTING_PROPERTY, property="vehicleType") 2@JsonSubTypes({ 3 @JsonSubTypes.Type(value = Car.class, name = "Car"), 4 @JsonSubTypes.Type(value = Truck.class, name = "Truck") 5}) 6/** 7 * Vehicle represents a union of types: Car, Truck 8 */ 9public interface Vehicle { 10 VehicleType getVehicleType(); 11} 12 13public class Car implements Vehicle { 14 @NotNull 15 @JsonProperty(\\"vehicleType\\") 16 private final VehicleType vehicleType = VehicleType.CAR; 17 private Map<String, Object> additionalProperties; 18 19 public VehicleType getVehicleType() { return this.vehicleType; } 20 21 public Map<String, Object> getAdditionalProperties() { return this.additionalProperties; } 22 public void setAdditionalProperties(Map<String, Object> additionalProperties) { this.additionalProperties = additionalProperties; } 23} 24 25public enum VehicleType { 26 CAR((String)"Car"), TRUCK((String)"Truck"); 27 28 private String value; 29 30 VehicleType(String value) { 31 this.value = value; 32 } 33 34 @JsonValue 35 public String getValue() { 36 return value; 37 } 38 39 @JsonCreator 40 public static VehicleType fromValue(String value) { 41 for (VehicleType e : VehicleType.values()) { 42 if (e.value.equals(value)) { 43 return e; 44 } 45 } 46 throw new IllegalArgumentException("Unexpected value '" + value + "'"); 47 } 48 49 @Override 50 public String toString() { 51 return String.valueOf(value); 52 } 53} 54 55public class Truck implements Vehicle { 56 @NotNull 57 @JsonProperty("vehicleType") 58 private final VehicleType vehicleType = VehicleType.TRUCK; 59 private Map<String, Object> additionalProperties; 60 61 public VehicleType getVehicleType() { return this.vehicleType; } 62 63 public Map<String, Object> getAdditionalProperties() { return this.additionalProperties; } 64 public void setAdditionalProperties(Map<String, Object> additionalProperties) { this.additionalProperties = additionalProperties; } 65}
OpenAPI inputs now generate parameters as models
For a given OpenAPI input, it now generates parameter models on top of the payload models as the default behavior.
renderCompleteModel
and render
now use object arguments
As parameters grow, regular arguments become cumbersome, so we are starting to switch over to using object arguments.
This means that the following functions are going to change from:
1generator.renderCompleteModel( 2 constrainedModel, 3 inputModel, 4 completeOptions, 5 options 6); 7 8generator.render( 9 constrainedModel, 10 inputModel, 11 options 12);
To
1generator.renderCompleteModel({ 2 constrainedModel, 3 inputModel, 4 completeOptions, 5 options 6}); 7 8generator.render({ 9 constrainedModel, 10 inputModel, 11 options 12});
Nullable models
Each meta model up until now was not able to be marked as nullable, but now they can be through isNullable
. Here are the different outputs and how they now apply nullable types.
TypeScript
Across all models, if they are nullable they will get the union x | null
.
JavaScript
Is not affected by this change.
C#
Is not affected by this change.
Java
With this update, Float, Integer, and Boolean meta models are rendered between their primitive types (for example float
) and wrapper classes (for example Float
) for nullable.
Double
now also respects being nullable.
Kotlin
Is not affected by this change.
Rust
Is not affected by this change.
Python
Is not affected by this change.
Go
Is not affected by this change.
Dart
Is not affected by this change.
C++
Is not affected by this change.
Upgrading to Node v18
As Node v14 is unmaintained we have upgraded to use Node v18.