-
Notifications
You must be signed in to change notification settings - Fork 224
Description
Describe the bug
for example, i have a struct :
type User struct {
UserName string `json:"username" xml:"username" yaml:"username" toml:"username" schema:"username" gorm:"column:username;not null;uniqueIndex:user_ids;default:'';"`
Password string `json:"password" xml:"password" yaml:"password" toml:"password" schema:"password" gorm:"column:password;not null;"`
}
i want to ignore field(Password) when Marshal but not unMarshal with go-toml.
so i define a function:
func (u *User) MarshalTOML() (any, error) {
type Alias User
tmp := &struct {
*Alias
// Explicitly exclude password by overriding it
Password string `toml:"-"`
}{
Alias: (*Alias)(u),
}
return tmp, nil
}
but it can not be called.
To Reproduce
Steps to reproduce the behavior. Including TOML files.
Expected behavior
My MarshalTOML for my struct can be called.
Versions
- go-toml: github.com/pelletier/go-toml/v2 v2.2.4
- go: go version
go version go1.23.6 darwin/amd64 - operating system:macOS
Additional context
Here's why My MarshalTOML method (as defined on *User) is not automatically called by toml.Marshal(yourUserObject):
toml.Marshal Flow:
toml.Marshal(v) calls NewEncoder(&buf).Encode(v).
Encoder.Encode(v) calls the internal enc.encode(b, ctx, reflect.ValueOf(v)).
Encoder.encode Logic:
The enc.encode method in marshaler.go uses reflect to determine how to serialize the value.
It checks for a few specific types (time.Time, LocalTime, etc.).
Crucially, it checks if the type implements encoding.TextMarshaler (which has a MarshalText() ([]byte, error) signature). If it does, that method is called, and the result is treated as a string. This is not the interface your MarshalTOML method implements.
Otherwise, it uses v.Kind() (e.g., reflect.Struct, reflect.Map, reflect.Slice) to decide how to proceed, recursively calling encode for elements or fields.
When it encounters a struct (like your User struct), it calls enc.encodeStruct, which then calls walkStruct. walkStruct iterates over the struct fields, respects their toml tags (like toml:"-" or toml:"name,omitempty"), but it does not check if the struct itself has a MarshalTOML() (any, error) method to replace itself with another value.