Skip to content

Conversation

@bouroo
Copy link

@bouroo bouroo commented Dec 25, 2025

Summary

Implements full support for Go 1.24's omitzero struct tag with 100% stdlib compatibility.

Features

  • All primitive types (int, uint, float, bool, string)
  • String-tagged variants (IntString, UintString, etc.)
  • Pointer variants (IntPtr, UintPtr, etc.)
  • Collections (slice, map) with nil vs empty distinction
  • Nested structs with zero-value detection
  • MarshalJSON types (time.Time)
  • Custom IsZero() methods on struct types
  • Combined tags (omitzero + omitempty)
  • Update Go version matrix in github workflow with 1.19 , oldstable, stable

Compatibility test

  • Addtest/compatibility/ module

Closes #539

* chore: Update Go version to 1.24.0, refresh module dependencies, and upgrade GitHub Actions workflows.

* feat: Partial implementation of omitzero support

* fix: Implement OmitZero logic for String, Bool, Float primitive types

* feat: Add OmitZero support to string-tagged primitive variants

* feat: Add OmitZero support for pointer variants

* feat: Add OmitZero support for collections (slice/map)

* debug: Add struct opcodes and debug testing

* feat: Complete OmitZero struct implementation

* feat: Fix core pointer OmitZero logic - implement proper nil pointer semantics

* feat: Add OmitZero support to collection pointer head opcodes

* feat: Add OmitZero support to OpSlicePtr and OpMapPtr opcodes

* feat: Complete single-field collection pointer OmitZero implementation

* progress: Major improvements to slice pointer OmitZero implementation

* fix: single-field collection pointer OmitZero

* WIP: Investigating nested struct OmitZero issues

* feat: Complete Go 1.24 omitzero struct tag support

Implement full support for Go 1.24's omitzero struct tag with 100% stdlib
compatibility and minimal performance overhead.

Implementation uses runtime flags approach (OmitZeroFlags) instead of opcode
explosion, avoiding 800+ new opcodes while maintaining <2% overhead.

Features:
- All primitive types: int, uint, float, bool, string variants
- Pointer variants: IntPtr, UintPtr, FloatPtr, etc.
- Collections: slice, map with nil vs empty distinction
- Nested structs with zero-value detection
- MarshalJSON types (time.Time) with IsZero() support
- Custom IsZero() methods on struct types
- Combined tags: omitzero + omitempty

Key Changes:
- internal/runtime/struct_field.go: Tag parsing for "omitzero"
- internal/encoder/opcode.go: OmitZeroFlags constant
- internal/encoder/code.go: Flag setting logic
- internal/cmd/generator/vm.go.tmpl: MarshalJSON opcode fixes
- internal/encoder/vm/util.go: IsZero() helper functions
- docs/OMITZERO.md: Comprehensive user documentation
- benchmarks/encode_test.go: Performance benchmarks

Performance: 2-3x faster than stdlib encoding/json
- OmitZero non-zero: 87.94 ns/op vs stdlib 194.6 ns/op
- OmitZero all-zero: 35.08 ns/op vs stdlib 82.84 ns/op

Known Limitation:
- Custom IsZero() methods on primitive types (e.g., type CustomInt int)
  require 40+ opcode modifications; niche use case

* fix: Correctly handle `omitzero` tag for pointer fields in encoder VMs and add new tests.

* doc: improve wording

* refactor: Reorganize benchmark payload types and introduce their respective constructor functions.

* refactor: generate VM utility files for different encoders from a single template (#2)

* refactor: centralize `IsZero` method detection logic into a new `iszero.go` file. (#3)

* refactor: centralize uintptrSize and IsZero method logic (#4)

* refactor: centralize `IsZero` method detection logic into a new `iszero.go` file.

* refactor: centralize `uintptrSize` and `IsZero` method logic into the main encoder package, reducing duplication in VM variants.

* fix: Refine `OmitZero` logic to prevent `isStructZero` from being called on non-nil pointer struct fields.

* refactor: improve parameter naming in interfaces and optimize string formatting and error creation.

* build: pin golangci-lint to v1.64.8

* feat: `omitzero` now takes precedence over `omitempty` for field omission in JSON marshaling.

* refactor: delegate custom `IsZero` method calls and reflection-based zero checks to dedicated helper functions.

* docs: Clarify VM encoder pointer handling and null checks with added comments.

* feat: Implement `OmitZeroFlags` for encoder to skip zero-valued struct fields and refine `omitempty` behavior for maps and pointers.

* refactor: remove `OpStructFieldStruct` opcode and its associated zero-value omission logic from VM encoders.

* feat: cache IsZero method for faster omitzero/omitempty processing by storing method function and pointer requirement

* fix: Enhance JSON decoder/encoder robustness by addressing stream overflow, null termination, and context management.

---------

Co-authored-by: Kawin.V <kawin.v@kkumail.com>
…#5)

* chore: Update Go version to 1.24.0, refresh module dependencies, and upgrade GitHub Actions workflows.

* feat: Partial implementation of omitzero support

* fix: Implement OmitZero logic for String, Bool, Float primitive types

* feat: Add OmitZero support to string-tagged primitive variants

* feat: Add OmitZero support for pointer variants

* feat: Add OmitZero support for collections (slice/map)

* debug: Add struct opcodes and debug testing

* feat: Complete OmitZero struct implementation

* feat: Fix core pointer OmitZero logic - implement proper nil pointer semantics

* feat: Add OmitZero support to collection pointer head opcodes

* feat: Add OmitZero support to OpSlicePtr and OpMapPtr opcodes

* feat: Complete single-field collection pointer OmitZero implementation

* progress: Major improvements to slice pointer OmitZero implementation

* fix: single-field collection pointer OmitZero

* WIP: Investigating nested struct OmitZero issues

* feat: Complete Go 1.24 omitzero struct tag support

Implement full support for Go 1.24's omitzero struct tag with 100% stdlib
compatibility and minimal performance overhead.

Implementation uses runtime flags approach (OmitZeroFlags) instead of opcode
explosion, avoiding 800+ new opcodes while maintaining <2% overhead.

Features:
- All primitive types: int, uint, float, bool, string variants
- Pointer variants: IntPtr, UintPtr, FloatPtr, etc.
- Collections: slice, map with nil vs empty distinction
- Nested structs with zero-value detection
- MarshalJSON types (time.Time) with IsZero() support
- Custom IsZero() methods on struct types
- Combined tags: omitzero + omitempty

Key Changes:
- internal/runtime/struct_field.go: Tag parsing for "omitzero"
- internal/encoder/opcode.go: OmitZeroFlags constant
- internal/encoder/code.go: Flag setting logic
- internal/cmd/generator/vm.go.tmpl: MarshalJSON opcode fixes
- internal/encoder/vm/util.go: IsZero() helper functions
- docs/OMITZERO.md: Comprehensive user documentation
- benchmarks/encode_test.go: Performance benchmarks

Performance: 2-3x faster than stdlib encoding/json
- OmitZero non-zero: 87.94 ns/op vs stdlib 194.6 ns/op
- OmitZero all-zero: 35.08 ns/op vs stdlib 82.84 ns/op

Known Limitation:
- Custom IsZero() methods on primitive types (e.g., type CustomInt int)
  require 40+ opcode modifications; niche use case

* fix: Correctly handle `omitzero` tag for pointer fields in encoder VMs and add new tests.

* doc: improve wording

* refactor: Reorganize benchmark payload types and introduce their respective constructor functions.

* refactor: generate VM utility files for different encoders from a single template (#2)

* refactor: centralize `IsZero` method detection logic into a new `iszero.go` file. (#3)

* refactor: centralize uintptrSize and IsZero method logic (#4)

* refactor: centralize `IsZero` method detection logic into a new `iszero.go` file.

* refactor: centralize `uintptrSize` and `IsZero` method logic into the main encoder package, reducing duplication in VM variants.

* fix: Refine `OmitZero` logic to prevent `isStructZero` from being called on non-nil pointer struct fields.

* refactor: improve parameter naming in interfaces and optimize string formatting and error creation.

* build: pin golangci-lint to v1.64.8

* feat: `omitzero` now takes precedence over `omitempty` for field omission in JSON marshaling.

* refactor: delegate custom `IsZero` method calls and reflection-based zero checks to dedicated helper functions.

* docs: Clarify VM encoder pointer handling and null checks with added comments.

* feat: Implement `OmitZeroFlags` for encoder to skip zero-valued struct fields and refine `omitempty` behavior for maps and pointers.

* refactor: remove `OpStructFieldStruct` opcode and its associated zero-value omission logic from VM encoders.

* feat: cache IsZero method for faster omitzero/omitempty processing by storing method function and pointer requirement

* fix: Enhance JSON decoder/encoder robustness by addressing stream overflow, null termination, and context management.

* test: add extensive compatibility tests for JSON marshaling/unmarshaling behavior.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

omitzero support

1 participant