From 3f0f92fb653d11eee6bb7d5f59e3d1c10c57040c Mon Sep 17 00:00:00 2001 From: Chao Yang Date: Fri, 28 Jan 2022 20:55:44 -0600 Subject: [PATCH] [crystal][client] Make optional properties nillable in models (#10723) * Add nillable data types to models Only REQUIRED and NOT NULLABLE variables can NOT have type Nil All OPTIONAL and NULLABLE-REQUIRED variables have type Nil Only NULLABLE-REQUIRED variables should emit keys with null values when they are serialized, json example: property name : String? = nil; the json representation for this property is {"name": null} For all OPTIONAL variables having Nil values, their variable keys would be skipped during serialization. The json representation for OPTIONAL property name : String? = nil; would be: {} * Fix failed tests in samples/client/petstore/crystal/spec/api/pet_api_spec.cr * Remove isNullable from model template * No need to check nillability of required property For any required property, assigning nil value to it will result in compilation error The datatype simply can not hold value nil, so there's no need to check it * Place required vars first in initializor * Refresh generated sample code for crystal client * Required properties are not nillable * Fix compilation error of undefined method equal? Crystal lang doesn't have method equal? We should use method same? instead of ruby's equal? method Reference: https://crystal-lang.org/api/master/Reference.html#same?(other:Reference):Bool-instance-method * Add tests for add_pet api endpoint with only required parameters Setting Pet optional properties to nil values is allowed by add_pet api endpoint * Add helper method to test compilation errors * Add tests to Pet model Test model initializations Test compilation error when model is initialized without required properties * Test required properties in json deserialization for Pet model --- .../crystal/partial_model_generic.mustache | 45 ++++++++----------- .../resources/crystal/spec_helper.mustache | 10 ++++- .../crystal/pet_compilation_error_spec.cr | 11 +++++ .../petstore/crystal/spec/api/pet_api_spec.cr | 39 +++++++++++----- .../petstore/crystal/spec/models/pet_spec.cr | 44 ++++++++++++++++-- .../petstore/crystal/spec/models/tag_spec.cr | 15 +++++++ .../petstore/crystal/spec/spec_helper.cr | 10 ++++- .../src/petstore/models/api_response.cr | 15 ++++--- .../crystal/src/petstore/models/category.cr | 11 ++--- .../crystal/src/petstore/models/order.cr | 27 +++++------ .../crystal/src/petstore/models/pet.cr | 40 +++++++---------- .../crystal/src/petstore/models/tag.cr | 11 ++--- .../crystal/src/petstore/models/user.cr | 35 ++++++++------- 13 files changed, 200 insertions(+), 113 deletions(-) create mode 100644 samples/client/petstore/crystal/pet_compilation_error_spec.cr diff --git a/modules/openapi-generator/src/main/resources/crystal/partial_model_generic.mustache b/modules/openapi-generator/src/main/resources/crystal/partial_model_generic.mustache index 4f2de178b0e..8e09ec2aba3 100644 --- a/modules/openapi-generator/src/main/resources/crystal/partial_model_generic.mustache +++ b/modules/openapi-generator/src/main/resources/crystal/partial_model_generic.mustache @@ -4,14 +4,28 @@ class {{classname}}{{#parent}} < {{{.}}}{{/parent}} include JSON::Serializable - {{#vars}} + {{#hasRequired}} + # Required properties + {{/hasRequired}} + {{#requiredVars}} {{#description}} # {{{.}}} {{/description}} - @[JSON::Field(key: "{{{baseName}}}", type: {{{dataType}}}{{#defaultValue}}, default: {{{defaultValue}}}{{/defaultValue}}{{#isNullable}}, nillable: true, emit_null: true{{/isNullable}})] + @[JSON::Field(key: "{{{baseName}}}", type: {{{dataType}}}{{#defaultValue}}, default: {{{defaultValue}}}{{/defaultValue}}, nillable: false, emit_null: false)] property {{{name}}} : {{{dataType}}} - {{/vars}} + {{/requiredVars}} + {{#hasOptional}} + # Optional properties + {{/hasOptional}} + {{#optionalVars}} + {{#description}} + # {{{.}}} + {{/description}} + @[JSON::Field(key: "{{{baseName}}}", type: {{{dataType}}}?{{#defaultValue}}, default: {{{defaultValue}}}{{/defaultValue}}, nillable: true, emit_null: false)] + property {{{name}}} : {{{dataType}}}? + + {{/optionalVars}} {{#hasEnums}} class EnumAttributeValidator getter datatype : String @@ -74,7 +88,7 @@ {{/discriminator}} # Initializes the object # @param [Hash] attributes Model attributes in the form of hash - def initialize({{#vars}}@{{{name}}} : {{{dataType}}}{{^required}}?{{/required}}{{^-last}}, {{/-last}}{{/vars}}) + def initialize({{#requiredVars}}@{{{name}}} : {{{dataType}}}{{^-last}}, {{/-last}}{{/requiredVars}}{{#hasRequired}}{{#hasOptional}}, {{/hasOptional}}{{/hasRequired}}{{#optionalVars}}@{{{name}}} : {{{dataType}}}?{{^-last}}, {{/-last}}{{/optionalVars}}) end # Show invalid properties with the reasons. Usually used together with valid? @@ -82,14 +96,6 @@ def list_invalid_properties invalid_properties = {{^parent}}Array(String).new{{/parent}}{{#parent}}super{{/parent}} {{#vars}} - {{^isNullable}} - {{#required}} - if @{{{name}}}.nil? - invalid_properties.push("invalid value for \"{{{name}}}\", {{{name}}} cannot be nil.") - end - - {{/required}} - {{/isNullable}} {{#hasValidation}} {{#maxLength}} if {{^required}}!@{{{name}}}.nil? && {{/required}}@{{{name}}}.to_s.size > {{{maxLength}}} @@ -143,11 +149,6 @@ # @return true if the model is valid def valid? {{#vars}} - {{^isNullable}} - {{#required}} - return false if @{{{name}}}.nil? - {{/required}} - {{/isNullable}} {{#isEnum}} {{^isContainer}} {{{name}}}_validator = EnumAttributeValidator.new("{{{dataType}}}", [{{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}}]) @@ -217,14 +218,6 @@ # Custom attribute writer method with validation # @param [Object] {{{name}}} Value to be assigned def {{{name}}}=({{{name}}}) - {{^isNullable}} - {{#required}} - if {{{name}}}.nil? - raise ArgumentError.new("{{{name}}} cannot be nil") - end - - {{/required}} - {{/isNullable}} {{#maxLength}} if {{^required}}!{{{name}}}.nil? && {{/required}}{{{name}}}.to_s.size > {{{maxLength}}} raise ArgumentError.new("invalid value for \"{{{name}}}\", the character length must be smaller than or equal to {{{maxLength}}}.") @@ -277,7 +270,7 @@ # Checks equality by comparing each attribute. # @param [Object] Object to be compared def ==(o) - return true if self.equal?(o) + return true if self.same?(o) self.class == o.class{{#vars}} && {{name}} == o.{{name}}{{/vars}}{{#parent}} && super(o){{/parent}} end diff --git a/modules/openapi-generator/src/main/resources/crystal/spec_helper.mustache b/modules/openapi-generator/src/main/resources/crystal/spec_helper.mustache index 9facafa4a93..56675bb6876 100644 --- a/modules/openapi-generator/src/main/resources/crystal/spec_helper.mustache +++ b/modules/openapi-generator/src/main/resources/crystal/spec_helper.mustache @@ -3,4 +3,12 @@ # load modules require "spec" require "json" -require "../src/{{{shardName}}}" \ No newline at end of file +require "../src/{{{shardName}}}" + +def assert_compilation_error(path : String, message : String) : Nil + buffer = IO::Memory.new + result = Process.run("crystal", ["run", "--no-color", "--no-codegen", path], error: buffer) + result.success?.should be_false + buffer.to_s.should contain message + buffer.close +end diff --git a/samples/client/petstore/crystal/pet_compilation_error_spec.cr b/samples/client/petstore/crystal/pet_compilation_error_spec.cr new file mode 100644 index 00000000000..519cb5b73e3 --- /dev/null +++ b/samples/client/petstore/crystal/pet_compilation_error_spec.cr @@ -0,0 +1,11 @@ +require "./spec/spec_helper" +require "json" +require "time" + +describe Petstore::Pet do + describe "test an instance of Pet" do + it "should fail to compile if any required properties is missing" do + pet = Petstore::Pet.new(id: nil, category: nil, name: nil, photo_urls: Array(String).new, tags: nil, status: nil) + end + end +end diff --git a/samples/client/petstore/crystal/spec/api/pet_api_spec.cr b/samples/client/petstore/crystal/spec/api/pet_api_spec.cr index 5c5f56295ac..5eb508ebd72 100644 --- a/samples/client/petstore/crystal/spec/api/pet_api_spec.cr +++ b/samples/client/petstore/crystal/spec/api/pet_api_spec.cr @@ -29,8 +29,28 @@ describe "PetApi" do # @param [Hash] opts the optional parameters # @return [Pet] describe "add_pet test" do - it "should work" do + it "should work with only required attributes" do # assertion here. ref: https://crystal-lang.org/reference/guides/testing.html + + config = Petstore::Configuration.new + config.access_token = "yyy" + config.api_key[:api_key] = "xxx" + config.api_key_prefix[:api_key] = "Token" + + api_client = Petstore::ApiClient.new(config) + + api_instance = Petstore::PetApi.new(api_client) + + pet_name = "new pet" + new_pet = Petstore::Pet.new(id: nil, category: nil, name: pet_name, photo_urls: Array(String).new, tags: nil, status: nil) + + pet = api_instance.add_pet(new_pet) + pet.id.should_not be_nil + pet.category.should be_nil + pet.name.should eq pet_name + pet.photo_urls.should eq Array(String).new + pet.status.should be_nil + pet.tags.should eq Array(Petstore::Tag).new end end @@ -89,20 +109,17 @@ describe "PetApi" do api_instance = Petstore::PetApi.new(api_client) - # create a pet to start with - pet_id = Int64.new(91829) - pet = Petstore::Pet.new(id: pet_id, category: Petstore::Category.new(id: pet_id + 10, name: "crystal category"), name: "crystal", photo_urls: ["https://crystal-lang.org"], tags: [Petstore::Tag.new(id: pet_id + 100, name: "crystal tag")], status: "available") - - api_instance.add_pet(pet) + new_pet = Petstore::Pet.new(id: nil, category: nil, name: "crystal", photo_urls: Array(String).new, tags: nil, status: nil) + pet = api_instance.add_pet(new_pet) + pet_id = pet.id.not_nil! result = api_instance.get_pet_by_id(pet_id: pet_id) result.id.should eq pet_id - result.category.id.should eq pet_id + 10 - result.category.name.should eq "crystal category" + result.category.should be_nil result.name.should eq "crystal" - result.photo_urls.should eq ["https://crystal-lang.org"] - result.status.should eq "available" - result.tags[0].id.should eq pet_id + 100 + result.photo_urls.should eq Array(String).new + result.status.should be_nil + result.tags.should eq Array(Petstore::Tag).new end end diff --git a/samples/client/petstore/crystal/spec/models/pet_spec.cr b/samples/client/petstore/crystal/spec/models/pet_spec.cr index d3eaf60dfc1..16117449db5 100644 --- a/samples/client/petstore/crystal/spec/models/pet_spec.cr +++ b/samples/client/petstore/crystal/spec/models/pet_spec.cr @@ -18,11 +18,49 @@ require "time" describe Petstore::Pet do describe "test an instance of Pet" do - it "should create an instance of Pet" do - #instance = Petstore::Pet.new - #expect(instance).to be_instance_of(Petstore::Pet) + it "should fail to compile if any required properties is missing" do + assert_compilation_error(path: "./pet_compilation_error_spec.cr", message: "Error: no overload matches 'Petstore::Pet.new', id: Nil, category: Nil, name: Nil, photo_urls: Array(String), tags: Nil, status: Nil") + end + + it "should create an instance of Pet with only required properties" do + pet = Petstore::Pet.new(id: nil, category: nil, name: "new pet", photo_urls: Array(String).new, tags: nil, status: nil) + pet.should be_a(Petstore::Pet) + end + + it "should create an instance of Pet with all properties" do + pet_id = 12345_i64 + pet = Petstore::Pet.new(id: pet_id, category: Petstore::Category.new(id: pet_id + 10, name: "crystal category"), name: "crystal", photo_urls: ["https://crystal-lang.org"], tags: [Petstore::Tag.new(id: pet_id + 100, name: "crystal tag")], status: "available") + pet.should be_a(Petstore::Pet) end end + + describe "#from_json" do + it "should instantiate a new instance from json string with required properties" do + pet = Petstore::Pet.from_json("{\"name\": \"json pet\", \"photoUrls\": []}") + pet.should be_a(Petstore::Pet) + pet.name.should eq "json pet" + pet.photo_urls.should eq Array(String).new + end + + it "should raise error when instantiating a new instance from json string with missing required properties" do + expect_raises(JSON::SerializableError, "Missing JSON attribute: name") do + Petstore::Pet.from_json("{\"photoUrls\": []}") + end + expect_raises(JSON::SerializableError, "Missing JSON attribute: photoUrls") do + Petstore::Pet.from_json("{\"name\": \"json pet\"}") + end + end + + it "should raise error when instantiating a new instance from json string with required properties set to null value" do + expect_raises(JSON::SerializableError, "Expected String but was Null") do + Petstore::Pet.from_json("{\"name\": null, \"photoUrls\": []}") + end + expect_raises(JSON::SerializableError, "Expected BeginArray but was Null") do + Petstore::Pet.from_json("{\"name\": \"json pet\", \"photoUrls\": null}") + end + end + end + describe "test attribute 'id'" do it "should work" do # assertion here. ref: https://crystal-lang.org/reference/guides/testing.html diff --git a/samples/client/petstore/crystal/spec/models/tag_spec.cr b/samples/client/petstore/crystal/spec/models/tag_spec.cr index f79e12657fc..64a05f292ce 100644 --- a/samples/client/petstore/crystal/spec/models/tag_spec.cr +++ b/samples/client/petstore/crystal/spec/models/tag_spec.cr @@ -23,6 +23,21 @@ describe Petstore::Tag do #expect(instance).to be_instance_of(Petstore::Tag) end end + + describe "test equality of Tag instances" do + it "should equal to itself" do + tag1 = Petstore::Tag.new(id: 0, name: "same") + tag2 = tag1 + (tag1 == tag2).should be_true + end + + it "should equal to another instance with same attributes" do + tag1 = Petstore::Tag.new(id: 0, name: "tag") + tag2 = Petstore::Tag.new(id: 0, name: "tag") + (tag1 == tag2).should be_true + end + end + describe "test attribute 'id'" do it "should work" do # assertion here. ref: https://crystal-lang.org/reference/guides/testing.html diff --git a/samples/client/petstore/crystal/spec/spec_helper.cr b/samples/client/petstore/crystal/spec/spec_helper.cr index c6eb4e7a603..7349161df1e 100644 --- a/samples/client/petstore/crystal/spec/spec_helper.cr +++ b/samples/client/petstore/crystal/spec/spec_helper.cr @@ -11,4 +11,12 @@ # load modules require "spec" require "json" -require "../src/petstore" \ No newline at end of file +require "../src/petstore" + +def assert_compilation_error(path : String, message : String) : Nil + buffer = IO::Memory.new + result = Process.run("crystal", ["run", "--no-color", "--no-codegen", path], error: buffer) + result.success?.should be_false + buffer.to_s.should contain message + buffer.close +end diff --git a/samples/client/petstore/crystal/src/petstore/models/api_response.cr b/samples/client/petstore/crystal/src/petstore/models/api_response.cr index be551134907..7a0719b6615 100644 --- a/samples/client/petstore/crystal/src/petstore/models/api_response.cr +++ b/samples/client/petstore/crystal/src/petstore/models/api_response.cr @@ -16,14 +16,15 @@ module Petstore class ApiResponse include JSON::Serializable - @[JSON::Field(key: "code", type: Int32)] - property code : Int32 + # Optional properties + @[JSON::Field(key: "code", type: Int32?, nillable: true, emit_null: false)] + property code : Int32? - @[JSON::Field(key: "type", type: String)] - property _type : String + @[JSON::Field(key: "type", type: String?, nillable: true, emit_null: false)] + property _type : String? - @[JSON::Field(key: "message", type: String)] - property message : String + @[JSON::Field(key: "message", type: String?, nillable: true, emit_null: false)] + property message : String? # Initializes the object # @param [Hash] attributes Model attributes in the form of hash @@ -46,7 +47,7 @@ module Petstore # Checks equality by comparing each attribute. # @param [Object] Object to be compared def ==(o) - return true if self.equal?(o) + return true if self.same?(o) self.class == o.class && code == o.code && _type == o._type && diff --git a/samples/client/petstore/crystal/src/petstore/models/category.cr b/samples/client/petstore/crystal/src/petstore/models/category.cr index 55c64154d97..65dd3f8cdd0 100644 --- a/samples/client/petstore/crystal/src/petstore/models/category.cr +++ b/samples/client/petstore/crystal/src/petstore/models/category.cr @@ -16,11 +16,12 @@ module Petstore class Category include JSON::Serializable - @[JSON::Field(key: "id", type: Int64)] - property id : Int64 + # Optional properties + @[JSON::Field(key: "id", type: Int64?, nillable: true, emit_null: false)] + property id : Int64? - @[JSON::Field(key: "name", type: String)] - property name : String + @[JSON::Field(key: "name", type: String?, nillable: true, emit_null: false)] + property name : String? # Initializes the object # @param [Hash] attributes Model attributes in the form of hash @@ -60,7 +61,7 @@ module Petstore # Checks equality by comparing each attribute. # @param [Object] Object to be compared def ==(o) - return true if self.equal?(o) + return true if self.same?(o) self.class == o.class && id == o.id && name == o.name diff --git a/samples/client/petstore/crystal/src/petstore/models/order.cr b/samples/client/petstore/crystal/src/petstore/models/order.cr index 5d00ea6688f..0536a0c3de6 100644 --- a/samples/client/petstore/crystal/src/petstore/models/order.cr +++ b/samples/client/petstore/crystal/src/petstore/models/order.cr @@ -16,24 +16,25 @@ module Petstore class Order include JSON::Serializable - @[JSON::Field(key: "id", type: Int64)] - property id : Int64 + # Optional properties + @[JSON::Field(key: "id", type: Int64?, nillable: true, emit_null: false)] + property id : Int64? - @[JSON::Field(key: "petId", type: Int64)] - property pet_id : Int64 + @[JSON::Field(key: "petId", type: Int64?, nillable: true, emit_null: false)] + property pet_id : Int64? - @[JSON::Field(key: "quantity", type: Int32)] - property quantity : Int32 + @[JSON::Field(key: "quantity", type: Int32?, nillable: true, emit_null: false)] + property quantity : Int32? - @[JSON::Field(key: "shipDate", type: Time)] - property ship_date : Time + @[JSON::Field(key: "shipDate", type: Time?, nillable: true, emit_null: false)] + property ship_date : Time? # Order Status - @[JSON::Field(key: "status", type: String)] - property status : String + @[JSON::Field(key: "status", type: String?, nillable: true, emit_null: false)] + property status : String? - @[JSON::Field(key: "complete", type: Bool, default: false)] - property complete : Bool + @[JSON::Field(key: "complete", type: Bool?, default: false, nillable: true, emit_null: false)] + property complete : Bool? class EnumAttributeValidator getter datatype : String @@ -91,7 +92,7 @@ module Petstore # Checks equality by comparing each attribute. # @param [Object] Object to be compared def ==(o) - return true if self.equal?(o) + return true if self.same?(o) self.class == o.class && id == o.id && pet_id == o.pet_id && diff --git a/samples/client/petstore/crystal/src/petstore/models/pet.cr b/samples/client/petstore/crystal/src/petstore/models/pet.cr index cdac65776d7..8edf5789c9a 100644 --- a/samples/client/petstore/crystal/src/petstore/models/pet.cr +++ b/samples/client/petstore/crystal/src/petstore/models/pet.cr @@ -16,24 +16,26 @@ module Petstore class Pet include JSON::Serializable - @[JSON::Field(key: "id", type: Int64)] - property id : Int64 - - @[JSON::Field(key: "category", type: Category)] - property category : Category - - @[JSON::Field(key: "name", type: String)] + # Required properties + @[JSON::Field(key: "name", type: String, nillable: false, emit_null: false)] property name : String - @[JSON::Field(key: "photoUrls", type: Array(String))] + @[JSON::Field(key: "photoUrls", type: Array(String), nillable: false, emit_null: false)] property photo_urls : Array(String) - @[JSON::Field(key: "tags", type: Array(Tag))] - property tags : Array(Tag) + # Optional properties + @[JSON::Field(key: "id", type: Int64?, nillable: true, emit_null: false)] + property id : Int64? + + @[JSON::Field(key: "category", type: Category?, nillable: true, emit_null: false)] + property category : Category? + + @[JSON::Field(key: "tags", type: Array(Tag)?, nillable: true, emit_null: false)] + property tags : Array(Tag)? # pet status in the store - @[JSON::Field(key: "status", type: String)] - property status : String + @[JSON::Field(key: "status", type: String?, nillable: true, emit_null: false)] + property status : String? class EnumAttributeValidator getter datatype : String @@ -60,29 +62,19 @@ module Petstore # Initializes the object # @param [Hash] attributes Model attributes in the form of hash - def initialize(@id : Int64?, @category : Category?, @name : String, @photo_urls : Array(String), @tags : Array(Tag)?, @status : String?) + def initialize(@name : String, @photo_urls : Array(String), @id : Int64?, @category : Category?, @tags : Array(Tag)?, @status : String?) end # Show invalid properties with the reasons. Usually used together with valid? # @return Array for valid properties with the reasons def list_invalid_properties invalid_properties = Array(String).new - if @name.nil? - invalid_properties.push("invalid value for \"name\", name cannot be nil.") - end - - if @photo_urls.nil? - invalid_properties.push("invalid value for \"photo_urls\", photo_urls cannot be nil.") - end - invalid_properties end # Check to see if the all the properties in the model are valid # @return true if the model is valid def valid? - return false if @name.nil? - return false if @photo_urls.nil? status_validator = EnumAttributeValidator.new("String", ["available", "pending", "sold"]) return false unless status_validator.valid?(@status) true @@ -101,7 +93,7 @@ module Petstore # Checks equality by comparing each attribute. # @param [Object] Object to be compared def ==(o) - return true if self.equal?(o) + return true if self.same?(o) self.class == o.class && id == o.id && category == o.category && diff --git a/samples/client/petstore/crystal/src/petstore/models/tag.cr b/samples/client/petstore/crystal/src/petstore/models/tag.cr index bd293329185..cd5e7ed2989 100644 --- a/samples/client/petstore/crystal/src/petstore/models/tag.cr +++ b/samples/client/petstore/crystal/src/petstore/models/tag.cr @@ -16,11 +16,12 @@ module Petstore class Tag include JSON::Serializable - @[JSON::Field(key: "id", type: Int64)] - property id : Int64 + # Optional properties + @[JSON::Field(key: "id", type: Int64?, nillable: true, emit_null: false)] + property id : Int64? - @[JSON::Field(key: "name", type: String)] - property name : String + @[JSON::Field(key: "name", type: String?, nillable: true, emit_null: false)] + property name : String? # Initializes the object # @param [Hash] attributes Model attributes in the form of hash @@ -43,7 +44,7 @@ module Petstore # Checks equality by comparing each attribute. # @param [Object] Object to be compared def ==(o) - return true if self.equal?(o) + return true if self.same?(o) self.class == o.class && id == o.id && name == o.name diff --git a/samples/client/petstore/crystal/src/petstore/models/user.cr b/samples/client/petstore/crystal/src/petstore/models/user.cr index 47430b4452a..a80b2574d2c 100644 --- a/samples/client/petstore/crystal/src/petstore/models/user.cr +++ b/samples/client/petstore/crystal/src/petstore/models/user.cr @@ -16,30 +16,31 @@ module Petstore class User include JSON::Serializable - @[JSON::Field(key: "id", type: Int64)] - property id : Int64 + # Optional properties + @[JSON::Field(key: "id", type: Int64?, nillable: true, emit_null: false)] + property id : Int64? - @[JSON::Field(key: "username", type: String)] - property username : String + @[JSON::Field(key: "username", type: String?, nillable: true, emit_null: false)] + property username : String? - @[JSON::Field(key: "firstName", type: String)] - property first_name : String + @[JSON::Field(key: "firstName", type: String?, nillable: true, emit_null: false)] + property first_name : String? - @[JSON::Field(key: "lastName", type: String)] - property last_name : String + @[JSON::Field(key: "lastName", type: String?, nillable: true, emit_null: false)] + property last_name : String? - @[JSON::Field(key: "email", type: String)] - property email : String + @[JSON::Field(key: "email", type: String?, nillable: true, emit_null: false)] + property email : String? - @[JSON::Field(key: "password", type: String)] - property password : String + @[JSON::Field(key: "password", type: String?, nillable: true, emit_null: false)] + property password : String? - @[JSON::Field(key: "phone", type: String)] - property phone : String + @[JSON::Field(key: "phone", type: String?, nillable: true, emit_null: false)] + property phone : String? # User Status - @[JSON::Field(key: "userStatus", type: Int32)] - property user_status : Int32 + @[JSON::Field(key: "userStatus", type: Int32?, nillable: true, emit_null: false)] + property user_status : Int32? # Initializes the object # @param [Hash] attributes Model attributes in the form of hash @@ -62,7 +63,7 @@ module Petstore # Checks equality by comparing each attribute. # @param [Object] Object to be compared def ==(o) - return true if self.equal?(o) + return true if self.same?(o) self.class == o.class && id == o.id && username == o.username &&