Files
Brad Fitzpatrick 483e2efcc0 types/jsonx: add wrapper types for JSON time and duration wire formats
Add DurationNano, DurationUnits, DurationISO8601, TimeUnix,
TimeUnixNano, and TimeRFC1123: wrappers around time.Duration and
time.Time that marshal to the wire formats that json `format:` struct
tag options (format:nano, format:units, and so on) used to produce
with github.com/go-json-experiment/json.

Go 1.27's encoding/json rejects format tag options outright, and the
module moved its support behind a global experimental option that its
documentation says will be removed (see golang/go#71631). Struct tags
are also only honored by the marshaler that happens to encode the
struct, so any stdlib encoding/json call reaching a tagged struct,
including generated MarshalJSON methods, breaks under Go 1.27. These
types instead carry their wire format with them: they implement both
the v1 json.Marshaler/Unmarshaler and the module's
MarshalerTo/UnmarshalerFrom interfaces and produce identical bytes
under the standard library and the module, on Go 1.26 and Go 1.27.
Tests verify byte-for-byte parity against the module's format tag
encodings across randomized values.

Unmarshal is additionally lenient where the legacy standard library
produced a different encoding for the underlying type because it
ignored the tags: the Time types also accept RFC 3339 strings and the
string-formatted Duration types also accept nanosecond counts, so
previously persisted data remains readable.

The tailscale corp repo will migrate its format tag uses to these
types; this repo has none.

Updates #20220
Updates tailscale/corp#45953

Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Change-Id: Iabde575b0228eb782d00e7180044ddd2f01d505e
2026-08-06 06:15:08 +00:00
..
2026-07-10 14:26:11 -07:00
2026-07-10 14:26:11 -07:00
2026-07-10 14:26:11 -07:00
2026-07-10 14:26:11 -07:00