OpenAPITools / OpenAPITools/openapi-generator
[REQ] [Go] Nullable* types should be easier to consume
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 26.8k
- Forks
- 7.7k
- PR merge metrics
- PR metrics pending
Description
Is your feature request related to a problem? Please describe.
openapi-generator 5.x introduced new Nullable types in the Golang code generator.
While "proper" nullables are useful, it's not entirely clear why they were implemented with pointer New()/Get()/Set() arguments and an additional isSet flag, instead of supporting plain values and using the nil pointer as a "is not set" marker.
Describe the solution you'd like
The Nullable* types should be replaced with pointer to type wrappers, New() and Set() should take a plain value and Get() should return a plain value.
Describe alternatives you've considered
The alternative is to use additional logic to check for nil values on every access to the Nullables. When creating a Nullable from a literal, it is necessary to create an intermediate variable first.
Additional context
With the current implementation, one has to do the following:
// works
s1 := "test"
ns1 := NewNullableString(&s1)
// does not work (can't construct a pointer to string literal)
ns2 := NewNullableString(&"test")
// works
var s3 string
if ns3.isSet() {
v3 := ns3.Get()
if v3 != nil {
s3 = *v3
}
}
// works
var s4 string
if ns4.isSet() && ns4.Get() != nil {
s4 = *ns4.Get()
}
// works, sets isSet to true, but the pointer to nil
ns5 := NewNullableString(nil)
// does not work, nil pointer dereference
ns6 := NewNullableString(nil)
var s6 string
if ns6.IsSet() {
s6 = *ns6.Get()
}
// works, sets isSet to false, but the pointer to non-nil (which doesn't make much sense)
s7 := "test"
ns7 := NullableString{&s7, false}
By getting rid of the isSet flag, using a wrapping type and replacing the New()/Get()/Set() functions with by-value versions, usage is more convenient:
type NullableString struct {
*string
}
func (v NullableString) Get() string {
if v.string != nil {
return *v.string
}
return ""
}
func (v *NullableString) Set(val string) {
v.string = &val
}
func (v NullableString) IsSet() bool {
return v.string != nil
}
func (v *NullableString) Unset() {
v.string = nil
}
func NewNullableString(val string) NullableString {
return NullableString{&val}
}
func (v NullableString) MarshalJSON() ([]byte, error) {
return json.Marshal(v.string)
}
func (v *NullableString) UnmarshalJSON(src []byte) error {
return json.Unmarshal(src, v.string)
}
Usage would then be like this:
// works
s1 := "test"
ns1 := NewNullableString(s1)
if !ns1.IsSet() {
panic("")
}
// works
ns2 := NewNullableString("test")
if !ns2.IsSet() {
panic("")
}
// works
s3 := "test"
ns3 := NullableString{&s3}
if !ns3.IsSet() {
panic("")
}
// works
ns4 := NewNullableString("test")
var s4 string
if ns4.IsSet() {
s4 = ns4.Get()
} else {
panic("")
}
if s4 != "test" {
panic("")
}
// works
ns5 := NewNullableString("test")
s5 := *ns5.string
if s5 != "test" {
panic("")
}
// works
ns6 := NullableString{nil}
if ns6.IsSet() {
panic("nil value should be unset")
}
// works, s7 is the empty string
ns7 := NullableString{nil}
s7 := ns7.Get()
if s7 != "" {
panic("")
}
// works
ns8 := NewNullableString("test")
ns8.MarshalJSON()
// works, s9 is the empty string
ns9 := NewNullableString("test")
ns9.Unset()
if ns9.IsSet() {
panic("")
}
s9 := ns9.Get()
if s9 != "" {
panic("")
}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the Go code generator's Nullable* implementation and trace how New(), Get(), Set(), IsSet(), Unset(), MarshalJSON(), and UnmarshalJSON() are generated. Compare the current behavior with the proposed pointer-wrapper design, including literal construction and nil handling. Done means the generated nullable types use by-value accessors without an isSet flag and preserve the intended JSON behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100