Migration from v2 to v3

This document contains all the breaking changes and migrations guidelines for adapting your code to the new version.

allowInheritance set to true will enable inheritance

This feature introduces a new option called allowInheritance in the interpreter options, which controls whether the generated models should inherit when the schema includes an allOf. By default, this option is set to false, which means that you'll not be affected if this property is not set. In the MetaModel and the ConstrainedMetaModel options, there is now an extend property (a list of models) and an isExtended property (boolean).

Here is an example of how to use the new feature and the allowInheritance option in your code:

1const generator = new JavaFileGenerator({
2  processorOptions: {
3    interpreter: {
4      allowInheritance: true
5    }
6  }
7});

TypeScript

JS reserved keywords are no longer applied by default

By default up until now, JS reserved keywords have been checked for TS as well. Which means that something like:

{
  $schema: 'http://json-schema.org/draft-07/schema#',
  type: 'object',
  additionalProperties: false,
  properties: {
    location: {
      type: 'string'
    }
  }
}

Would be default be rendered as:

1class Root {
2  private _reservedLocation?: string;
3
4  constructor(input: {
5    reservedLocation?: string,
6  }) {
7    this._reservedLocation = input.reservedLocation;
8  }
9
10  get reservedLocation(): string | undefined { return this._reservedLocation; }
11  set reservedLocation(reservedLocation: string | undefined) { this._reservedLocation = reservedLocation; }
12}

However, without setting useJavascriptReservedKeywords: true by default the following will be generated:

1class Root {
2  private _location?: string;
3
4  constructor(input: {
5    location?: string,
6  }) {
7    this._location = input.location;
8  }
9
10  get location(): string | undefined { return this._location; }
11  set location(location: string | undefined) { this._location = location; }
12}

JavaScript

Is not affected by this change.

C#

System.TimeSpan is used when format is time

This example used to generate a string, but is now instead using System.TimeSpan.

1type: object
2properties:
3  duration:
4    type: string
5    format: time

will generate

1public class TestClass {
2  private System.TimeSpan duration;
3  ...
4}

System.DateTime is used when format is date-time

This example used to generate a string, but is now instead using System.DateTime.

1type: object
2properties:
3  dob:
4    type: string
5    format: date-time

will generate

1public class TestClass {
2  private System.DateTime dob;
3  ...
4}

System.Guid is used when format is uuid

This example used to generate a string, but is now instead using System.Guid.

1type: object
2properties:
3  uniqueId:
4    type: string
5    format: uuid

will generate

1public class TestClass {
2  private System.Guid uniqueId;
3  ...
4}

Java

java.time.Duration is used when format is duration

This example used to generate a String, but is now instead using java.time.Duration.

1type: object
2properties:
3  duration:
4    type: string
5    format: duration

will generate

1public class TestClass {
2  private java.time.Duration duration;
3  ...
4}

inheritance will generate interfaces

Please read the section about allowInheritance first. When allowInheritance is enabled, interfaces will be generated for schemas that uses allOf:

1components:
2  messages:
3    Vehicle:
4      payload:
5        oneOf:
6          - $ref: '#/components/schemas/Car'
7          - $ref: '#/components/schemas/Truck'
8  schemas:
9    Vehicle:
10      title: Vehicle
11      type: object
12      discriminator: vehicleType
13      properties:
14        vehicleType:
15          title: VehicleType
16          type: string
17        length:
18          type: number
19          format: float
20      required:
21        - vehicleType
22    Car:
23      allOf:
24        - '#/components/schemas/Vehicle'
25        - type: object
26          properties:
27            vehicleType:
28              const: Car
29    Truck:
30      allOf:
31        - '#/components/schemas/Vehicle'
32        - type: object
33          properties:
34            vehicleType:
35              const: Truck

will generate

1public interface NewVehicle {
2  VehicleType getVehicleType();
3}
4
5public class Car implements NewVehicle, Vehicle {
6  private final VehicleType vehicleType = VehicleType.CAR;
7  private Float length;
8  private Map<String, Object> additionalProperties;
9
10  public VehicleType getVehicleType() { return this.vehicleType; }
11
12  @Override
13  public Float getLength() { return this.length; }
14  @Override
15  public void setLength(Float length) { this.length = length; }
16}
17
18public enum VehicleType {
19  CAR((String)\\"Car\\"), TRUCK((String)\\"Truck\\");
20
21  private String value;
22
23  VehicleType(String value) {
24    this.value = value;
25  }
26
27  public String getValue() {
28    return value;
29  }
30
31  public static VehicleType fromValue(String value) {
32    for (VehicleType e : VehicleType.values()) {
33      if (e.value.equals(value)) {
34        return e;
35      }
36    }
37    throw new IllegalArgumentException(\\"Unexpected value '\\" + value + \\"'\\");
38  }
39
40  @Override
41  public String toString() {
42    return String.valueOf(value);
43  }
44}
45
46public interface Vehicle {
47  public Float getLength();
48  public void setLength(Float length);
49}
50
51public class Truck implements NewVehicle, Vehicle {
52  private final VehicleType vehicleType = VehicleType.TRUCK;
53  private Float length;
54  private Map<String, Object> additionalProperties;
55
56  public VehicleType getVehicleType() { return this.vehicleType; }
57
58  @Override
59  public Float getLength() { return this.length; }
60  @Override
61  public void setLength(Float length) { this.length = length; }
62}

Kotlin

Is not affected by this change.

Rust

Is not affected by this change.

Python

Union type for the Pydantic preset supports Python pre 3.10

Modelina used to use the newer way of representing unions in Python by using the | operator. In the Pydantic preset, this is now adjusted to support Python pre 3.10 by using Union[Model1, Model2] instead:

1title: UnionTest
2type: object
3  properties:
4    unionTest:
5      oneOf:
6        - title: Union1
7          type: object
8          properties:
9            testProp1:
10              type: string
11        - title: Union2
12          type: object
13          properties:
14            testProp2:
15              type: string

will generate

1class UnionTest(BaseModel):
2  unionTest: Optional[Union[Union1, Union2]] = Field()
3  additionalProperties: Optional[dict[Any, Any]] = Field()
4
5class Union1(BaseModel):
6  testProp1: Optional[str] = Field()
7  additionalProperties: Optional[dict[Any, Any]] = Field()
8
9class Union2(BaseModel):
10  testProp2: Optional[str] = Field()
11  additionalProperties: Optional[dict[Any, Any]] = Field()

Go

Is not affected by this change.

Dart

Is not affected by this change.

C++

Is not affected by this change.

Options in constraints

As part of https://github.com/asyncapi/modelina/issues/1475 we had the need to access options in the constraint logic, therefore all constraints now have direct access to the provided options.

To make it easier we now expose types for each of the constraints in each language to make it easier to re-use in TS integrations. They can be accessed as following:

1import { <language>ConstantConstraint, <language>EnumKeyConstraint, <language>EnumValueConstraint, <language>ModelNameConstraint, <language>PropertyKeyConstraint } from @asyncapi/modelina