-
-
Notifications
You must be signed in to change notification settings - Fork 6.9k
Go struct members pointers #3241
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -35,9 +35,95 @@ type {{classname}} struct { | |||
{{#description}} | ||||
// {{{description}}} | ||||
{{/description}} | ||||
{{name}} {{#isNullable}}*{{/isNullable}}{{{dataType}}} `json:"{{baseName}}{{^required}},omitempty{{/required}}"{{#withXml}} xml:"{{baseName}}{{#isXmlAttribute}},attr{{/isXmlAttribute}}"{{/withXml}}{{#vendorExtensions.x-go-custom-tag}} {{{.}}}{{/vendorExtensions.x-go-custom-tag}}` | ||||
{{name}} *{{{dataType}}} `json:"{{baseName}},omitempty"{{#withXml}} xml:"{{baseName}}{{#isXmlAttribute}},attr{{/isXmlAttribute}}"{{/withXml}}{{#vendorExtensions.x-go-custom-tag}} {{{.}}}{{/vendorExtensions.x-go-custom-tag}}` | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. also, it's breaking backward-compatibility. the field shouldn't twiddle between pointer and non-pointer at least There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I've had a discussion about this with @wing328 and we'll probably create another go client generator to accept this change (and possibly other breaking changes) that would otherwise be unacceptable for 4.1.x and would have to wait for 5.0.0 - which would be a loooong time. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @bkabrda For the new go generator, would you mind tagging it with "Experimental" Line 19 in 6e1c897
It would look like this in the new generator's constructor:
This will allow us to tag/filter generators to clearly present which ones are considered stable to users. |
||||
{{#isNullable}} isExplicitNull{{name}} bool `json:"-"{{#withXml}} xml:"-"{{/withXml}}`{{/isNullable}} | ||||
{{/vars}} | ||||
} | ||||
{{/isEnum}} | ||||
|
||||
{{^isEnum}} | ||||
{{#vars}} | ||||
// Get{{name}} returns the {{name}} field if non-nil, zero value otherwise. | ||||
func (o *{{classname}}) Get{{name}}() {{dataType}} { | ||||
if o == nil || o.{{name}} == nil { | ||||
var ret {{dataType}} | ||||
return ret | ||||
} | ||||
return *o.{{name}} | ||||
} | ||||
|
||||
// Get{{name}}Ok returns a tuple with the {{name}} field if it's non-nil, zero value otherwise | ||||
// and a boolean to check if the value has been set. | ||||
func (o *{{classname}}) Get{{name}}Ok() ({{dataType}}, bool) { | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the name doesn't really sonuds ok.. in favor of others e.g. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I actually prefer |
||||
if o == nil || o.{{name}} == nil { | ||||
var ret {{dataType}} | ||||
return ret, false | ||||
} | ||||
return *o.{{name}}, true | ||||
} | ||||
|
||||
// Has{{name}} returns a boolean if a field has been set. | ||||
func (o *{{classname}}) Has{{name}}() bool { | ||||
if o != nil && o.{{name}} != nil { | ||||
return true | ||||
} | ||||
|
||||
return false | ||||
} | ||||
|
||||
// Set{{name}} gets a reference to the given {{dataType}} and assigns it to the {{name}} field. | ||||
func (o *{{classname}}) Set{{name}}(v {{dataType}}) { | ||||
o.{{name}} = &v | ||||
} | ||||
|
||||
{{#isNullable}} | ||||
// Set{{name}}ExplicitNull (un)sets {{name}} to be considered as explicit "null" value | ||||
// when serializing to JSON (pass true as argument to set this, false to unset) | ||||
// The {{name}} value is set to nil even if false is passed | ||||
func (o *{{classname}}) Set{{name}}ExplicitNull(b bool) { | ||||
o.{{name}} = nil | ||||
o.isExplicitNull{{name}} = b | ||||
} | ||||
{{/isNullable}} | ||||
{{/vars}} | ||||
|
||||
func (o {{classname}}) MarshalJSON() ([]byte, error) { | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||
toSerialize := map[string]interface{}{} | ||||
{{#vars}} | ||||
{{#required}} | ||||
{{! if argument is required and not nullable, it can't be nil}} | ||||
{{^isNullable}} | ||||
if o.{{name}} == nil { | ||||
return nil, errors.New("{{name}} is required and not nullable, but was not set on {{classname}}") | ||||
}{{/isNullable}} | ||||
{{! if argument is required and nullable, it *must* have isExplicitNull<name> set to true when it's nil}} | ||||
{{#isNullable}} | ||||
if o.{{name}} == nil && !o.isExplicitNull{{name}} { | ||||
return nil, errors.New("{{name}} is required and nullable, but it wasn't set to be explicit null") | ||||
} | ||||
{{/isNullable}} | ||||
{{/required}} | ||||
{{! if argument is nullable, only serialize it if it is nil *and* was explicitly set to nil}} | ||||
{{#isNullable}} | ||||
if o.{{name}} == nil { | ||||
if o.isExplicitNull{{name}} { | ||||
toSerialize["{{baseName}}"] = o.{{name}} | ||||
} | ||||
} else { | ||||
toSerialize["{{baseName}}"] = o.{{name}} | ||||
} | ||||
{{/isNullable}} | ||||
{{! if argument is not nullable, don't set it if it is nil}} | ||||
{{^isNullable}} | ||||
if o.{{name}} != nil { | ||||
toSerialize["{{baseName}}"] = o.{{name}} | ||||
} | ||||
{{/isNullable}} | ||||
{{/vars}} | ||||
return json.Marshal(toSerialize) | ||||
} | ||||
|
||||
{{/isEnum}} | ||||
|
||||
{{/model}} | ||||
{{/models}} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
{{>partial_header}} | ||
package {{packageName}} | ||
|
||
import "time" | ||
|
||
// PtrBool is a helper routine that returns a pointer to given integer value. | ||
func PtrBool(v bool) *bool { return &v } | ||
|
||
// PtrInt is a helper routine that returns a pointer to given integer value. | ||
func PtrInt(v int) *int { return &v } | ||
|
||
// PtrInt32 is a helper routine that returns a pointer to given integer value. | ||
func PtrInt32(v int32) *int32 { return &v } | ||
|
||
// PtrInt64 is a helper routine that returns a pointer to given integer value. | ||
func PtrInt64(v int64) *int64 { return &v } | ||
|
||
// PtrFloat is a helper routine that returns a pointer to given float value. | ||
func PtrFloat(v float32) *float32 { return &v } | ||
|
||
// PtrFloat32 is a helper routine that returns a pointer to given float value. | ||
func PtrFloat32(v float32) *float32 { return &v } | ||
|
||
// PtrFloat64 is a helper routine that returns a pointer to given float value. | ||
func PtrFloat64(v float64) *float64 { return &v } | ||
|
||
// PtrString is a helper routine that returns a pointer to given string value. | ||
func PtrString(v string) *string { return &v } | ||
|
||
// PtrTime is helper routine that returns a pointer to given Time value. | ||
func PtrTime(v time.Time) *time.Time { return &v } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what's the point of adding a field
isExplicitNull
to mark it explicity? as a convention of go, it's a nullable if it's a pointer, otoh, a non-pointer field means it's a non-optional fieldThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The point is to be able to have a field that can be sent with
null
as a value. The whole point of this PR is that it's very hard in Go to have fields that allow setting either a zero value (0, false, empty string) or anull
explicitly. This PR allows for various combinations of all of these features thanks toisExplicitNull
and the custom marshalling.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I notice that {{#isNullable}} ... {{/isNullable}} has been removed. Does it mean model properties with or without nullable set to true are handled the same way?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are handled explicitly in the custom marshalling method, see https://github.com/OpenAPITools/openapi-generator/pull/3241/files#diff-6403a68f6b1039398715805f9043d0a1R95 and following lines.