Skip to content

how to ignore fields when Marshal but not unMarshal with go-toml? #987

@snowdream

Description

@snowdream

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions