ESD-1554: accept string and null dates in Time.UnmarshalJSON - #168
Open
Phil-Browne wants to merge 5 commits into
Open
ESD-1554: accept string and null dates in Time.UnmarshalJSON#168Phil-Browne wants to merge 5 commits into
Phil-Browne wants to merge 5 commits into
Conversation
Phil-Browne
force-pushed
the
fix/time-unmarshal-string-dates
branch
3 times, most recently
from
June 29, 2026 16:34
fec4379 to
120f1b3
Compare
Time.UnmarshalJSON only decoded JSON numbers (Unix epoch milliseconds), so any endpoint or environment that returns an ISO 8601 date string made the unmarshal error out. That error failed the decode of the whole response and surfaced to users as an empty resource list. Accept date strings (RFC3339/ISO 8601, with or without offset, plus date-only), a quoted numeric epoch, and null/empty values (mapped to the zero time), so a single string-valued date can no longer empty a list. The plain numeric epoch path is unchanged, so existing responses decode exactly as before. A quoted digit string outside the year 2000-2100 epoch window is treated as a date, not an epoch, so a compact date cannot silently decode to a 1970-era or far-future timestamp. Truly unparseable values still error. Adds table-driven tests covering each form plus the null handling for both pointer and value Time fields.
Phil-Browne
force-pushed
the
fix/time-unmarshal-string-dates
branch
from
June 29, 2026 17:00
120f1b3 to
c6e4c72
Compare
Phil-Browne
marked this pull request as ready for review
July 6, 2026 23:44
Jackson-based backends emit offsets like +0000, which the RFC3339 layouts reject; add a Z0700 layout covering both fractional and whole-second forms.
Assert the full decoded instant instead of just .Year(), which would have passed even if month/day/time were mangled.
time.RFC3339Nano precedes it in timeStringLayouts and accepts everything it would, so the entry never matched.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Time.UnmarshalJSONonly decoded JSON numbers (Unix epoch milliseconds). Any date value that arrived as a string made the unmarshal error out, and that error failed the decode of the whole response, surfacing to users as an empty resource list. TheTimetype backs date fields on ports, VXCs, MCRs, MVEs, IXs, service keys, and locations, so this affects every list/get path.Note: the spec is not uniform here. The product DTOs declare these dates as non-nullable epoch-millisecond integers, so for ports, VXCs, MCRs, MVEs and service keys this is defensive broadening rather than a documented mismatch. But
MegaportLocation.liveDate, behindGET /v2/locations, is a documenteddate-timestring that the SDK decodes intoLocation.LiveDate *Time, so at least one mapping would have failed on the old numeric-only path. That the v2 location methods are deprecated is probably why nobody hit it. Either way this costs nothing on the unchanged numeric path.The unmarshaller now also accepts:
"1700000000000")null/ empty, mapped to the zero timeThe plain numeric epoch path is unchanged, so existing responses decode exactly as before (same timezone, same precision). A single string-valued date can no longer empty a list. A quoted digit string outside the year 2000-2100 epoch-millisecond window is treated as a date rather than an epoch, so a compact date like
20260629or20260629010203can't silently decode to a 1970-era or far-future timestamp. Truly unparseable values still return an error.Adds table-driven tests for each input form plus struct-level regression tests covering null on both pointer and value
Timefields.No CHANGELOG entry: the file is organized by released version with no Unreleased section, so entries are added at release time.
Type of change
Contributor Agreement
[I have read and accept the CLA]