There are a few cases where the library overzealously applies both optional() and nullable(). This change aims to restrict the cases to match the actual possible output from marshaling JSON in Go (see examples. It also fixes one case where the type was too restrictive. These cases are outlined below.
Changes
Remove optional() from struct fields tagged as omitempty that are themselves structs because these cannot be empty
Example:
type Foo struct {
X struct {
S string
} `json:",omitempty"`
}
Output before for X:
X: z.object({
S: z.string()
}).optional()
Output after for X:
X: z.object({
S: z.string()
})
Remove nullable() from pointer types not pointing to a slice, another pointer, or a map that are tagged as omitempty because these cannot be exported as null
Example:
type Foo struct {
A string `json: ",omitempty"`
B *string `json: ",omitempty"`
C **string `json: ",omitempty"`
}
In the case of pointers to slices and maps tagged as omitempty, the result is unchanged because these can be exported with the value null or undefined. Pointers to interfaces can also be exported with the value null but interfaces already have type any so adding nullable() to that doesn't make sense.
Add nullable() to map fields that are not tagged as omitempty because these can be exported as null
Example:
type Foo struct {
M map[string]string
M map[string]string `json:",omitempty"`
O *map[string]string `json:",omitempty"`
}
In the case of maps tagged as omitempty, the result is unchanged because these cannot be exported with the value null, but since the previous code didn't correctly add the nullable() annotation, these issues cancel either out. Also, in the case of pointers to maps tagged as omitempty, the result is unchanged because these can be exported with null or undefined values.
Overview
There are a few cases where the library overzealously applies both
optional()
andnullable()
. This change aims to restrict the cases to match the actual possible output from marshaling JSON in Go (see examples. It also fixes one case where the type was too restrictive. These cases are outlined below.Changes
Remove
optional()
from struct fields tagged asomitempty
that are themselves structs because these cannot be emptyExample:
Output before for
X
:Output after for
X
:Remove
nullable()
from pointer types not pointing to a slice, another pointer, or a map that are tagged asomitempty
because these cannot be exported asnull
Example:
Output before for
A
,B
, andC
:Output after:
Note that pointers to pointers can still be
null
because only the value outermost pointer is checked for empty value in the case ofomitempty
.Remove
nullable()
from slice fields that are tagged asomitempty
because these cannot be exported asnull
Example:
Output before for
X
,Y
:Output after for
X
,Y
:In the case of pointers to slices and maps tagged as
omitempty
, the result is unchanged because these can be exported with the valuenull
orundefined
. Pointers to interfaces can also be exported with the value null but interfaces already have typeany
so addingnullable()
to that doesn't make sense.Add
nullable()
to map fields that are not tagged asomitempty
because these can be exported asnull
Example:
Output before for
N
,M
, andO
:Output after for
N
,M
, andO
:In the case of maps tagged as
omitempty
, the result is unchanged because these cannot be exported with the valuenull
, but since the previous code didn't correctly add thenullable()
annotation, these issues cancel either out. Also, in the case of pointers to maps tagged asomitempty
, the result is unchanged because these can be exported withnull
orundefined
values.