mirror of
https://github.com/rclone/rclone.git
synced 2024-11-25 01:44:41 +01:00
fs: improve JSON Unmarshalling for Duration
Enhanced the UnmarshalJSON method for the Duration type to correctly handle the special string 'off' and ensure large integers are parsed accurately without floating-point rounding errors. This resolves issues with setting and removing the MinAge filter through the rclone rc command. Fixes #3783 Co-authored-by: Kyle Reynolds <kyle.reynolds@bridgerphotonics.com>
This commit is contained in:
parent
00fb847662
commit
7803b4ed6c
@ -1,6 +1,7 @@
|
|||||||
package fs
|
package fs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -231,10 +232,26 @@ func (d Duration) Type() string {
|
|||||||
|
|
||||||
// UnmarshalJSON makes sure the value can be parsed as a string or integer in JSON
|
// UnmarshalJSON makes sure the value can be parsed as a string or integer in JSON
|
||||||
func (d *Duration) UnmarshalJSON(in []byte) error {
|
func (d *Duration) UnmarshalJSON(in []byte) error {
|
||||||
return UnmarshalJSONFlag(in, d, func(i int64) error {
|
// Check if the input is a string value.
|
||||||
|
if len(in) >= 2 && in[0] == '"' && in[len(in)-1] == '"' {
|
||||||
|
strVal := string(in[1 : len(in)-1]) // Remove the quotes
|
||||||
|
|
||||||
|
// Attempt to parse the string as a duration.
|
||||||
|
parsedDuration, err := ParseDuration(strVal)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*d = Duration(parsedDuration)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// Handle numeric values.
|
||||||
|
var i int64
|
||||||
|
err := json.Unmarshal(in, &i)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
*d = Duration(i)
|
*d = Duration(i)
|
||||||
return nil
|
return nil
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan implements the fmt.Scanner interface
|
// Scan implements the fmt.Scanner interface
|
||||||
|
@ -214,3 +214,32 @@ func TestParseUnmarshalJSON(t *testing.T) {
|
|||||||
assert.Equal(t, Duration(test.want), duration, test.in)
|
assert.Equal(t, Duration(test.want), duration, test.in)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUnmarshalJSON(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
input string
|
||||||
|
want Duration
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{"off string", `"off"`, DurationOff, false},
|
||||||
|
{"max int64", `9223372036854775807`, DurationOff, false},
|
||||||
|
{"duration string", `"1h"`, Duration(time.Hour), false},
|
||||||
|
{"invalid string", `"invalid"`, 0, true},
|
||||||
|
{"negative int", `-1`, Duration(-1), false},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
var d Duration
|
||||||
|
err := json.Unmarshal([]byte(tt.input), &d)
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("UnmarshalJSON() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if d != tt.want {
|
||||||
|
t.Errorf("UnmarshalJSON() got = %v, want %v", d, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user