I'm using time.Duration
to store data in a struct as follows:
type ApiAccessToken struct {
...
ExpiredIn *time.Duration `bson:"expired_in,omitempty" json:"expired_in,omitempty"`
...
}
and I set it using a constant like this:
...
const ApiAccessTokenDefaultExpiresIn = 7 * 24 * time.Hour
...
d := ApiAccessTokenDefaultExpiresIn
data := &ApiAccessToken{
...
ExpiredIn: &d
...
}
...
then I use mgo
to insert the data to database.
I did checking after creating the data
instance and before inserting the data and the value of ExpiredIn
was 604'800'000'000'000 but in MongoDB it became 604'800'000 (or NumberLong(604800000)
).
Any idea why? Thank you!
We would normally write custom MarshalJSON/UnmarshalJSON for specific types to control what happens to their values before/after marshaling/unmarshaling.
type ExpiredIn struct {
time.Duration
}
func (e *ExpiredIn) MarshalJSON() ([]byte, error) {
return []byte(string(e.Nanoseconds())), nil
}
func (e *ExpiredIn) UnmarshalJSON(data []byte) error {
i, _ := strconv.ParseInt(string(data[:])), 10, 64)
e.Duration = time.Duration(i)
return nil
}
Here's the test code:
package main
import (
"log"
"time"
"gopkg.in/mgo.v2"
)
type Token struct {
ExpiredIn time.Duration
}
type ExpiredIn struct {
time.Duration
}
func (e *ExpiredIn) MarshalJSON() ([]byte, error) {
return []byte(string(e.Nanoseconds())), nil
}
func main() {
session, err := mgo.Dial("mongodb://localhost:27017/test")
if err != nil {
panic(err)
}
defer session.Close()
// Optional. Switch the session to a monotonic behavior.
session.SetMode(mgo.Monotonic, true)
c := session.DB("test").C("tokens")
err = c.Insert(&Recipe{7 * 24 * time.Hour})
if err != nil {
log.Fatal(err)
}
}
And you're done!
Current solution: multiply the returned
ExpiredIn
from MongoDB with
time.Second
so I got my Go-flavoured nanosecond
time.Duration
.
I ended up using the string
representation of time.Duration
because it simply works.
I created two functions for my ApiAccessToken
struct that does the job of writing/reading the data.
func (tok *ApiAccessToken) SetExpiredIn(t time.Duration) {
s := t.String() // read the string
tok.ExpiredIn = &s
}
func (tok *ApiAccessToken) GetExpiredIn() (r bool, t time.Duration) {
if tok.ExpiredIn != nil {
var err error
t, err = time.ParseDuration(*tok.ExpiredIn) // parse the string
r = (err == nil) // can we use this?
}
return
}
And voila, it works!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.