Skip to content

Commit 1b281b8

Browse files
authored
GODRIVER-2119 Implement Text(Un)Marshaler for primitive.ObjectID (#715)
1 parent f6a3ed8 commit 1b281b8

File tree

2 files changed

+49
-0
lines changed

2 files changed

+49
-0
lines changed

bson/primitive/objectid.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ package primitive
1212
import (
1313
"bytes"
1414
"crypto/rand"
15+
"encoding"
1516
"encoding/binary"
1617
"encoding/hex"
1718
"encoding/json"
@@ -34,6 +35,9 @@ var NilObjectID ObjectID
3435
var objectIDCounter = readRandomUint32()
3536
var processUnique = processUniqueBytes()
3637

38+
var _ encoding.TextMarshaler = ObjectID{}
39+
var _ encoding.TextUnmarshaler = ObjectID{}
40+
3741
// NewObjectID generates a new ObjectID.
3842
func NewObjectID() ObjectID {
3943
return NewObjectIDFromTimestamp(time.Now())
@@ -94,6 +98,19 @@ func IsValidObjectID(s string) bool {
9498
return err == nil
9599
}
96100

101+
// MarshalText returns the ObjectID as UTF-8-encoded text. Implementing this allows us to use ObjectID
102+
// as a map key when marshalling JSON. See https://pkg.go.dev/encoding#TextMarshaler
103+
func (id ObjectID) MarshalText() ([]byte, error) {
104+
return []byte(id.Hex()), nil
105+
}
106+
107+
// UnmarshalText populates the byte slice with the ObjectID. Implementing this allows us to use ObjectID
108+
// as a map key when unmarshalling JSON. See https://pkg.go.dev/encoding#TextUnmarshaler
109+
func (id ObjectID) UnmarshalText(b []byte) error {
110+
id, err := ObjectIDFromHex(string(b))
111+
return err
112+
}
113+
97114
// MarshalJSON returns the ObjectID as a string
98115
func (id ObjectID) MarshalJSON() ([]byte, error) {
99116
return json.Marshal(id.Hex())

bson/primitive/objectid_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,38 @@ func TestCounterOverflow(t *testing.T) {
172172
require.Equal(t, uint32(0), objectIDCounter)
173173
}
174174

175+
func TestObjectID_MarshalJSONMap(t *testing.T) {
176+
type mapOID struct {
177+
Map map[ObjectID]string
178+
}
179+
180+
oid := NewObjectID()
181+
expectedJSON := []byte(fmt.Sprintf(`{"Map":{%q:"foo"}}`, oid.Hex()))
182+
data := mapOID{
183+
Map: map[ObjectID]string{oid: "foo"},
184+
}
185+
186+
out, err := json.Marshal(&data)
187+
require.NoError(t, err)
188+
require.Equal(t, expectedJSON, out)
189+
}
190+
191+
func TestObjectID_UnmarshalJSONMap(t *testing.T) {
192+
type mapOID struct {
193+
Map map[ObjectID]string
194+
}
195+
oid := NewObjectID()
196+
mapOIDJSON := []byte(fmt.Sprintf(`{"Map":{%q:"foo"}}`, oid.Hex()))
197+
expectedData := mapOID{
198+
Map: map[ObjectID]string{oid: "foo"},
199+
}
200+
201+
data := mapOID{}
202+
err := json.Unmarshal(mapOIDJSON, &data)
203+
require.NoError(t, err)
204+
require.Equal(t, expectedData, data)
205+
}
206+
175207
func TestObjectID_UnmarshalJSON(t *testing.T) {
176208
oid := NewObjectID()
177209

0 commit comments

Comments
 (0)