Set json encoding precision (#162)

This commit is contained in:
Michael Fridman 2022-02-09 21:54:31 -05:00 committed by GitHub
parent 863d23d08a
commit 279dd19720
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 54 additions and 6 deletions

View File

@ -49,9 +49,13 @@ func newNumericDateFromSeconds(f float64) *NumericDate {
// MarshalJSON is an implementation of the json.RawMessage interface and serializes the UNIX epoch // MarshalJSON is an implementation of the json.RawMessage interface and serializes the UNIX epoch
// represented in NumericDate to a byte array, using the precision specified in TimePrecision. // represented in NumericDate to a byte array, using the precision specified in TimePrecision.
func (date NumericDate) MarshalJSON() (b []byte, err error) { func (date NumericDate) MarshalJSON() (b []byte, err error) {
var prec int
if TimePrecision < time.Second {
prec = int(math.Log10(float64(time.Second) / float64(TimePrecision)))
}
f := float64(date.Truncate(TimePrecision).UnixNano()) / float64(time.Second) f := float64(date.Truncate(TimePrecision).UnixNano()) / float64(time.Second)
return []byte(strconv.FormatFloat(f, 'f', -1, 64)), nil return []byte(strconv.FormatFloat(f, 'f', prec, 64)), nil
} }
// UnmarshalJSON is an implementation of the json.RawMessage interface and deserializses a // UnmarshalJSON is an implementation of the json.RawMessage interface and deserializses a

View File

@ -18,12 +18,10 @@ func TestNumericDate(t *testing.T) {
jwt.TimePrecision = time.Microsecond jwt.TimePrecision = time.Microsecond
raw := `{"iat":1516239022,"exp":1516239022.12345}` raw := `{"iat":1516239022.000000,"exp":1516239022.123450}`
err := json.Unmarshal([]byte(raw), &s) if err := json.Unmarshal([]byte(raw), &s); err != nil {
t.Fatalf("Unexpected error: %s", err)
if err != nil {
t.Errorf("Unexpected error: %s", err)
} }
b, _ := json.Marshal(s) b, _ := json.Marshal(s)
@ -65,3 +63,49 @@ func TestSingleArrayMarshal(t *testing.T) {
t.Errorf("Serialized format of string array mismatch. Expecting: %s Got: %s", string(expected), string(b)) t.Errorf("Serialized format of string array mismatch. Expecting: %s Got: %s", string(expected), string(b))
} }
} }
func TestNumericDate_MarshalJSON(t *testing.T) {
// Do not run this test in parallel because it's changing
// global state.
oldPrecision := jwt.TimePrecision
t.Cleanup(func() {
jwt.TimePrecision = oldPrecision
})
tt := []struct {
in time.Time
want string
precision time.Duration
}{
{time.Unix(5243700879, 0), "5243700879", time.Second},
{time.Unix(5243700879, 0), "5243700879.000", time.Millisecond},
{time.Unix(5243700879, 0), "5243700879.000001", time.Microsecond},
{time.Unix(5243700879, 0), "5243700879.000000954", time.Nanosecond},
//
{time.Unix(4239425898, 0), "4239425898", time.Second},
{time.Unix(4239425898, 0), "4239425898.000", time.Millisecond},
{time.Unix(4239425898, 0), "4239425898.000000", time.Microsecond},
{time.Unix(4239425898, 0), "4239425898.000000000", time.Nanosecond},
//
{time.Unix(0, 1644285000210402000), "1644285000", time.Second},
{time.Unix(0, 1644285000210402000), "1644285000.210", time.Millisecond},
{time.Unix(0, 1644285000210402000), "1644285000.210402", time.Microsecond},
{time.Unix(0, 1644285000210402000), "1644285000.210402012", time.Nanosecond},
//
{time.Unix(0, 1644285315063096000), "1644285315", time.Second},
{time.Unix(0, 1644285315063096000), "1644285315.063", time.Millisecond},
{time.Unix(0, 1644285315063096000), "1644285315.063096", time.Microsecond},
{time.Unix(0, 1644285315063096000), "1644285315.063096046", time.Nanosecond},
}
for i, tc := range tt {
jwt.TimePrecision = tc.precision
by, err := jwt.NewNumericDate(tc.in).MarshalJSON()
if err != nil {
t.Fatal(err)
}
if got := string(by); got != tc.want {
t.Errorf("[%d]: failed encoding: got %q want %q", i, got, tc.want)
}
}
}