Skip to content

json.Marshal with omitzero broken on decimal.Zero #405

@abemedia

Description

@abemedia

Go v1.24 introduced the iszero tag: https://pkg.go.dev/encoding/json#Marshal

The "omitzero" option specifies that the field should be omitted from the encoding if the field has a zero value, according to rules:

  1. If the field type has an "IsZero() bool" method, that will be used to determine whether the value is zero.

  2. Otherwise, the value is zero if it is the zero value for its type.

This works great for decimal.Decimal as it implements IsZero, however it breaks when using a nested struct containing decimal.Zero, as the struct now no longer is the zero value.

See this example: https://go.dev/play/p/E5ZACVij_Rh

My suggestion is to use var Zero Decimal, and to ensure it doesn't need to initialise when using calculations, we can implement this:

var zeroValue = new(big.Int)

func (d *Decimal) getValue() *big.Int {
	if d.value == nil {
		return zeroValue
	}
	return d.value
}

That way we never need to initialise a zero value Decimal for a calculation as they all use the same pointer.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions