Skip to content

Commit fe69c82

Browse files
author
Divjot Arora
authored
GODRIVER-1542 Add DateTime.UnmarshalJSON (#355)
1 parent 94b769f commit fe69c82

File tree

2 files changed

+46
-0
lines changed

2 files changed

+46
-0
lines changed

bson/primitive/primitive.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,32 @@ type Undefined struct{}
4040
// DateTime represents the BSON datetime value.
4141
type DateTime int64
4242

43+
var _ json.Marshaler = DateTime(0)
44+
var _ json.Unmarshaler = (*DateTime)(nil)
45+
4346
// MarshalJSON marshal to time type
4447
func (d DateTime) MarshalJSON() ([]byte, error) {
4548
return json.Marshal(d.Time())
4649
}
4750

51+
// UnmarshalJSON creates a primitive.DateTime from a JSON string.
52+
func (d *DateTime) UnmarshalJSON(data []byte) error {
53+
// Ignore "null" to keep parity with the time.Time type and the standard library. Decoding "null" into a non-pointer
54+
// DateTime field will leave the field unchanged. For pointer values, the encoding/json will set the pointer to nil
55+
// and will not defer to the UnmarshalJSON hook.
56+
if string(data) == "null" {
57+
return nil
58+
}
59+
60+
var tempTime time.Time
61+
if err := json.Unmarshal(data, &tempTime); err != nil {
62+
return err
63+
}
64+
65+
*d = NewDateTimeFromTime(tempTime)
66+
return nil
67+
}
68+
4869
// Time returns the date as a time type.
4970
func (d DateTime) Time() time.Time {
5071
return time.Unix(int64(d)/1000, int64(d)%1000*1000000)

bson/primitive/primitive_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77
package primitive
88

99
import (
10+
"encoding/json"
1011
"testing"
1112

1213
"github.com/stretchr/testify/require"
14+
"go.mongodb.org/mongo-driver/internal/testutil/assert"
1315
)
1416

1517
// The same interface as bsoncodec.Zeroer implemented for tests.
@@ -78,3 +80,26 @@ func TestRegexCompare(t *testing.T) {
7880
})
7981
}
8082
}
83+
84+
func TestDateTime(t *testing.T) {
85+
t.Run("json", func(t *testing.T) {
86+
t.Run("round trip", func(t *testing.T) {
87+
original := DateTime(1000)
88+
jsonBytes, err := json.Marshal(original)
89+
assert.Nil(t, err, "Marshal error: %v", err)
90+
91+
var unmarshalled DateTime
92+
err = json.Unmarshal(jsonBytes, &unmarshalled)
93+
assert.Nil(t, err, "Unmarshal error: %v", err)
94+
95+
assert.Equal(t, original, unmarshalled, "expected DateTime %v, got %v", original, unmarshalled)
96+
})
97+
t.Run("decode null", func(t *testing.T) {
98+
jsonBytes := []byte("null")
99+
var dt DateTime
100+
err := json.Unmarshal(jsonBytes, &dt)
101+
assert.Nil(t, err, "Unmarshal error: %v", err)
102+
assert.Equal(t, DateTime(0), dt, "expected DateTime value to be 0, got %v", dt)
103+
})
104+
})
105+
}

0 commit comments

Comments
 (0)