Skip to content

Commit

Permalink
Swap UUID format to byte array
Browse files Browse the repository at this point in the history
With deepmap#546 merged in, UUIDs are defined as an alias for a string.

Before that implementation gets mass adoption, I wanted to propose a
slightly different alternative: basing the custom type off of
`uuid.UUID` over `string`.

This has the advantages of:
- Being convertable back to a `uuid.UUID` without having to parse the
  string a second time, or opening the conversion up to failure
  scenarios
- Still being easily convertable to `string` with the `uuid.UUID`'s
  `String` method
- Taking up less space in memory
- Reducing the number of invalid representations, since only `[16]byte`s
  can be represented, as opposed to all strings
- Not adding any dependencies, since `uuid.UUID` is already being
  imported
  • Loading branch information
rliebz committed Apr 21, 2022
1 parent 9dc8b8d commit 184ea74
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 14 deletions.
12 changes: 5 additions & 7 deletions pkg/types/uuid.go
Expand Up @@ -7,23 +7,21 @@ import (
"github.com/google/uuid"
)

type UUID string
type UUID uuid.UUID

func (u UUID) MarshalJSON() ([]byte, error) {
if _, err := uuid.Parse(string(u)); err != nil {
return nil, errors.New("uuid: failed to pass validation")
}
return json.Marshal(string(u))
return json.Marshal(uuid.UUID(u).String())
}

func (u *UUID) UnmarshalJSON(data []byte) error {
var s string
if err := json.Unmarshal(data, &s); err != nil {
return err
}
if _, err := uuid.Parse(s); err != nil {
parsed, err := uuid.Parse(s)
if err != nil {
return errors.New("uuid: failed to pass validation")
}
*u = UUID(s)
*u = UUID(parsed)
return nil
}
16 changes: 9 additions & 7 deletions pkg/types/uuid_test.go
Expand Up @@ -4,22 +4,24 @@ import (
"encoding/json"
"testing"

"github.com/google/uuid"
"github.com/stretchr/testify/assert"
)

func TestUUID_MarshalJSON_Fail(t *testing.T) {
testUUID := "this-is-not-a-uuid"
func TestUUID_MarshalJSON_Zero(t *testing.T) {
var testUUID UUID
b := struct {
UUIDField UUID `json:"uuid"`
}{
UUIDField: UUID(testUUID),
UUIDField: testUUID,
}
_, err := json.Marshal(b)
assert.Error(t, err)
marshaled, err := json.Marshal(b)
assert.NoError(t, err)
assert.JSONEq(t, `{"uuid":"00000000-0000-0000-0000-000000000000"}`, string(marshaled))
}

func TestUUID_MarshalJSON_Pass(t *testing.T) {
testUUID := "9cb14230-b640-11ec-b909-0242ac120002"
testUUID := uuid.MustParse("9cb14230-b640-11ec-b909-0242ac120002")
b := struct {
UUIDField UUID `json:"uuid"`
}{
Expand All @@ -40,7 +42,7 @@ func TestUUID_UnmarshalJSON_Fail(t *testing.T) {
}

func TestUUID_UnmarshalJSON_Pass(t *testing.T) {
testUUID := UUID("9cb14230-b640-11ec-b909-0242ac120002")
testUUID := UUID(uuid.MustParse("9cb14230-b640-11ec-b909-0242ac120002"))
jsonStr := `{"uuid":"9cb14230-b640-11ec-b909-0242ac120002"}`
b := struct {
UUIDField UUID `json:"uuid"`
Expand Down

0 comments on commit 184ea74

Please sign in to comment.