-
-
Notifications
You must be signed in to change notification settings - Fork 7.3k
Description
Bug Report Checklist
- Have you provided a full/minimal spec to reproduce the issue?
- Have you validated the input using an OpenAPI validator?
- Have you tested with the latest master to confirm the issue still exists?
- Have you searched for related issues/PRs?
- What's the actual output vs expected output?
- [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description
The issue: the current Crystal generator generates code with wrongly typed variables.
openapi-generator version
master
Generation Details
The story :
The current Crystal generator generates this code :
For example, to destroy bookmarks in bulk I can use this method :
# @param bookmark_request [Array(BookmarkRequest)]
def extras_bookmarks_bulk_destroy(bookmark_request : Array(BookmarkRequest))which needs an array of BookmarkRequest :
module NetboxClient
# Extends the built-in ModelSerializer to enforce calling full_clean() on a copy of the associated instance during validation. (DRF does not do this by default; see https://github.com/encode/django-rest-framework/issues/3144)
class BookmarkRequest
include JSON::Serializable
include YAML::Serializable
# Required properties
@[JSON::Field(key: "object_type", type: String, nillable: false, emit_null: false)]
property object_type : String
@[JSON::Field(key: "object_id", type: Int64, nillable: false, emit_null: false)]
property object_id : Int64
@[JSON::Field(key: "user", type: BookmarkRequestUser, nillable: false, emit_null: false)]
property user : BookmarkRequestUserIn BookmarkRequest there is a field user of type BookmarkRequestUser :
BookmarkRequestUser is actually not a type but more a factory that builds the real type (BriefUserRequest or Int32) depending on the data passed to the build(data) method :
module NetboxClient
module BookmarkRequestUser
class SchemaMismatchError < Exception
end
# List of class defined in oneOf (OpenAPI v3)
def self.openapi_one_of
[
BriefUserRequest,
Int32,
]
end
def self.build(data)
# Go through the list of oneOf items and attempt to identify the appropriate one.
# Note:
# - We do not attempt to check whether exactly one item matches.
# - No advanced validation of types in some cases (e.g. "x: { type: string }" will happily match { x: 123 })
# due to the way the deserialization is made in the base_object template (it just casts without verifying).
# - TODO: scalar values are de facto behaving as if they were nullable.
# - TODO: logging when debugging is set.
openapi_one_of.each do |klass|
begin
# next if klass == :AnyType # "nullable: true"
typed_data = find_and_cast_into_type(klass, data)
return typed_data if typed_data
rescue # rescue all errors so we keep iterating even if the current item lookup raises
end
end
# openapi_one_of.includes?(:AnyType) ? data : nil
nil
endOne of the real type is BriefUserRequest which take a single string username :
module NetboxClient
# Extends the built-in ModelSerializer to enforce calling full_clean() on a copy of the associated instance during validation. (DRF does not do this by default; see https://github.com/encode/django-rest-framework/issues/3144)
class BriefUserRequest
include JSON::Serializable
include YAML::Serializable
# Required properties
# Requis. 150 caractères maximum. Uniquement des lettres, nombres et les caractères « @ », « . », « + », « - » et « _ ».
@[JSON::Field(key: "username", type: String, nillable: false, emit_null: false)]
property username : StringSo let's try to delete some bookmarks :
def self.delete_bookmarks
# Recall:
# class BookmarkRequest
# @[JSON::Field(key: "user", type: BookmarkRequestUser, nillable: false, emit_null: false)]
# property user : BookmarkRequestUser
user = NetboxClient::BookmarkRequestUser.build(NetboxClient::RecursiveHash.new({"username" => "foo"}))
object = NetboxClient::BookmarkRequest.new(object_type: "Device", object_id: 42.to_i64, user: user)
puts YAML.dump(object)
endBut because the final type NetboxClient::BriefUserRequest does not match with NetboxClient::BookmarkRequestUser it doesn't compile :
In src/netbox_extractor/controllers/test_api.cr:39:95
39 | object = NetboxClient::BookmarkRequest.new(object_type: "Device", object_id: 42.to_i64, user: user)
^
Error: expected argument 'user' to 'NetboxClient::BookmarkRequest.new' to be NetboxClient::BookmarkRequestUser, not (Int32 | NetboxClient::BriefUserRequest | Nil)Suggest a fix
To solve this I'd like to change model definition from :
module NetboxClient
# Extends the built-in ModelSerializer to enforce calling full_clean() on a copy of the associated instance during validation. (DRF does not do this by default; see https://github.com/encode/django-rest-framework/issues/3144)
class BookmarkRequest
include JSON::Serializable
include YAML::Serializable
# Required properties
@[JSON::Field(key: "object_type", type: String, nillable: false, emit_null: false)]
property object_type : String
@[JSON::Field(key: "object_id", type: Int64, nillable: false, emit_null: false)]
property object_id : Int64
@[JSON::Field(key: "user", type: BookmarkRequestUser, nillable: false, emit_null: false)]
property user : BookmarkRequestUserto
module NetboxClient
# Extends the built-in ModelSerializer to enforce calling full_clean() on a copy of the associated instance during validation. (DRF does not do this by default; see https://github.com/encode/django-rest-framework/issues/3144)
class BookmarkRequest
include JSON::Serializable
include YAML::Serializable
# Required properties
@[JSON::Field(key: "object_type", type: String, nillable: false, emit_null: false)]
property object_type : String
@[JSON::Field(key: "object_id", type: Int64, nillable: false, emit_null: false)]
property object_id : Int64
@[JSON::Field(key: "user", type: BriefUserRequest | Int32, nillable: false, emit_null: false)] # <= here
property user : BriefUserRequest | Int32 # <= and herebut I don't know if it's feasible.
or make won't workBriefUserRequest a generic? I don't know.