Migrating to goenums v0.6

Migrating to goenums v0.6

Version 0.6 improves generated serialization, numeric parsing, validation, and CLI error reporting. Because goenums is pre-1.0, this minor release contains behavior changes that may require regeneration flags or small source updates.

  1. Upgrade the goenums binary.
  2. Review the behavior changes below.
  3. Add -legacy-text to existing //go:generate directives if your application depends on quoted MarshalText output.
  4. Run go generate ./....
  5. Review generated diffs and run your full test suite.

Text marshaling

New default

Generated MarshalText methods now follow encoding.TextMarshaler conventions and return raw enum text:

text, _ := Statuses.ACTIVE.MarshalText()
fmt.Printf("%s", text) // Active

Before v0.6, the generated method returned JSON-quoted text:

"Active"

Compatibility mode

If existing consumers require the old quoted output, add -legacy-text when generating:

//go:generate goenums -legacy-text status.go

or from the command line:

goenums -legacy-text status.go

This generates the pre-v0.6 behavior:

func (s Status) MarshalText() ([]byte, error) {
    return []byte("\"" + s.String() + "\""), nil
}

For programmatic generator use, set the corresponding configuration field:

configuration := config.Configuration{
    LegacyTextMarshal: true,
}

LegacyTextMarshal affects only MarshalText; it does not change JSON marshaling.

JSON marshaling and unmarshaling

Generated MarshalJSON now uses json.Marshal so aliases containing quotes, backslashes, newlines, or other control characters are escaped as valid JSON. Ordinary enum values continue to marshal as JSON strings:

"Active"

Generated UnmarshalJSON accepts both:

  • standard JSON string input, as supplied by json.Unmarshal; and
  • raw enum text passed directly to UnmarshalJSON, for compatibility with earlier generated code.
var status Status
_ = json.Unmarshal([]byte(`"Active"`), &status) // standard usage
_ = status.UnmarshalJSON([]byte("Active"))     // direct-call compatibility

New integrations should use standard JSON strings. The raw-text path exists for compatibility and should not be relied upon as a general JSON parser.

Numeric parsing

Numeric input now matches the enum’s underlying constant value rather than its ordinal position.

type result int

const (
    Unknown result = -1
    Success result = 0
    Failure result = 1
)

With v0.6:

ParseResult(0) // Success
ParseResult(1) // Failure

Review callers for enums with negative or non-zero starts, explicit values, or gaps.

Custom-field validation

The number of metadata values on each enum declaration must now exactly match the fields declared on the enum type. Previously, missing or extra values could be silently truncated or ignored.

type planet int // Gravity float64, Radius float64

const (
    Earth planet = iota // 9.81, 6371 // valid: two values
)

Fix malformed enum comments before regenerating. In failfast mode, generation returns an error immediately; otherwise the malformed enum is marked invalid.

Selective interface generation

v0.6 adds --interfaces as an opt-in way to reduce generated API surface. Defaults are unchanged: if the flag is omitted, JSON, Text, YAML, SQL, and Binary handlers are all generated.

goenums --interfaces=json,sql status.go

Valid values are json, text, yaml, sql, and binary.

-legacy-text only affects generated Text handlers. If text is not selected, -legacy-text has no generated-code effect.

This feature is additive and does not require migration unless you want to reduce generated methods.

CLI exit status

Unsupported input formats, unsupported output formats, and generation failures now return a non-zero process exit status consistently. Scripts that previously depended on a successful exit after a logged error should be updated.

Compatibility summary

Change v0.6 default Compatibility option
MarshalText Raw text Generate with -legacy-text
MarshalJSON Standards-compliant JSON escaping No option; ordinary output is unchanged
UnmarshalJSON JSON strings plus raw direct-call fallback Raw fallback is built in
Numeric parsing Underlying constant values with local constraints by default Update callers that used ordinal positions; use -x-exp-constraints only if you prefer the external constraints package
Custom fields Exact value count required Fix malformed declarations
Selective interfaces All handlers still generated by default Use --interfaces=json,sql to reduce generated methods
CLI errors Non-zero exit status Update scripts