oatpp / oatpp-swagger

OpenApi 3.0.0 docs + Swagger UI for oatpp services
https://oatpp.io/
Apache License 2.0
95 stars 54 forks source link

Support for schemas which better reflect DTO polymorphic fields #88

Open OneDevTwoDev opened 12 months ago

OneDevTwoDev commented 12 months ago

I've been following along with some of the discussion on a prior issue in the oatpp repo here: https://github.com/oatpp/oatpp/issues/405

While I've been able to implement a polymorphic DTO field as demonstrated in the linked issue and 1.3.0 changelog for oatpp, I've been curious about potential enhancements to the OAS schema generation in the oatpp-swagger tool that better reflect the intent of the polymorphic fields.

If I have a set of Vehicle classes like so:

ENUM(VehicleType, v_uint8,
  VALUE(SUV, 0),
  VALUE(TRUCK, 1)
)

class SuvProperties : public oatpp::DTO {
   DTO_INIT(SuvProperties, DTO)

  DTO_FIELD(UInt8, pax_count);
};

class TruckProperties : public oatpp::DTO {
  DTO_INIT(TruckProperties, DTO)

  DTO_FIELD(UInt32, towing_capacity_in_lbs);
};

class Vehicle : public oatpp::DTO {
  DTO_INIT(Vehicle, DTO)

  DTO_FIELD(Enum<VehicleType>::AsString, vehicle_type);
  DTO_FIELD(Any, vehicle_properties);

  DTO_FIELD_TYPE_SELECTOR(vehicle_properties) {
    switch(*vehicle_type) {
      case VehicleType::SUV: return Object<SuvProperties>::Class::getType();
      case VehicleType::TRUCK: return Object<TruckProperties>::Class::getType();
    }
  }
};

Currently, the above classes would generate the following jsonschema in the swagger specification:

schemas:
  Vehicle:
    type: object
    properties:
      vehicle_type:
        type: string
        enum:
          0: SUV
          1: TRUCK
      vehicle_properties:
        type: Any

I personally haven't found the "Any" type to be very useful. It doesn't convey to the documentation consumer that there are actually only two valid configurations of data that will conform to this schema, I know jsonschema provides the oneOf and discriminator syntax for addressing this exact case that would look something like:

schemas:
  SUV:
    type: object
    properties:
      vehicle_type:
        type: string
      vehicle_properties:
        type: object
        properties:
          pax_count:
            type: integer
 TRUCK:
   type: object
   properties:
     vehicle_type:
       type: string
     vehicle_properties:
       type: object
       properties:
         towing_capacity_in_lbs:
           type: integer
  Vehicle:
    oneOf:
      - $ref: "#/components/schemas/SUV
      - $ref: "#/components/schemas/TRUCK
    discriminator:
      propertyName: vehicle_type

I believe the above schema should generate more helpful prompting and documentation in the swagger tool about the allowed configurations, but currently the only way I can see to generate schemas like this is to write the json documentation by hand and then replicate the functionality of the swagger controller, but with a static json file that is manually maintained.

Not sure whether support for something like this is feasible currently, but figured I'd ask since I was curious about it.