Skip to content
Snippets Groups Projects
Commit d6318fbb authored by Jono Wenger's avatar Jono Wenger
Browse files

Add support for json.Marshal and json.Unmarshal to id.ID

parent 53405cf1
No related branches found
No related tags found
2 merge requests!24Release,!20Add support for json.Marshal and json.Unmarshal to id.ID
......@@ -15,6 +15,7 @@ import (
"encoding/base64"
"encoding/binary"
"encoding/hex"
"encoding/json"
"github.com/pkg/errors"
jww "github.com/spf13/jwalterweatherman"
"io"
......@@ -112,6 +113,30 @@ func (id *ID) SetType(idType Type) {
id[ArrIDLen-1] = byte(idType)
}
// UnmarshalJSON is part of the json.Unmarshaler interface and allows IDs to be
// marshaled into JSON.
func (id *ID) UnmarshalJSON(b []byte) error {
var buff []byte
if err := json.Unmarshal(b, &buff); err != nil {
return err
}
newID, err := Unmarshal(buff)
if err != nil {
return err
}
*id = *newID
return nil
}
// MarshalJSON is part of the json.Marshaler interface and allows IDs to be
// marshaled into JSON.
func (id ID) MarshalJSON() ([]byte, error) {
return json.Marshal(id.Marshal())
}
// NewRandomID generates a random ID using the passed in io.Reader r
// and sets the ID to Type t. If the base64 string of the generated
// ID does not begin with an alphanumeric character, then another ID
......
......@@ -10,6 +10,7 @@ import (
"bytes"
"encoding/base64"
"encoding/binary"
"encoding/json"
"fmt"
"math/rand"
"reflect"
......@@ -301,6 +302,50 @@ func TestID_SetType_NilError(t *testing.T) {
id.SetType(Generic)
}
// Tests that an ID can be JSON marshaled and unmarshalled.
func TestID_MarshalJSON_UnmarshalJSON(t *testing.T) {
testID := NewIdFromBytes(rngBytes(ArrIDLen, 42, t), t)
jsonData, err := json.Marshal(testID)
if err != nil {
t.Errorf("json.Marshal returned an error: %+v", err)
}
newID := &ID{}
err = json.Unmarshal(jsonData, newID)
if err != nil {
t.Errorf("json.Unmarshal returned an error: %+v", err)
}
if *testID != *newID {
t.Errorf("Failed the JSON marshal and unmarshal ID."+
"\noriginal ID: %s\nreceived ID: %s", testID, newID)
}
}
// Error path: supplied data is invalid JSON.
func TestID_UnmarshalJSON_JsonUnmarshalError(t *testing.T) {
expectedErr := "invalid character"
id := ID{}
err := id.UnmarshalJSON([]byte("invalid JSON"))
if err == nil || !strings.Contains(err.Error(), expectedErr) {
t.Errorf("UnmarshalJSON failed to return the expected error for "+
"invalid JSON.\nexpected: %s\nreceived: %+v", expectedErr, err)
}
}
// Error path: supplied data is valid JSON but an invalid ID.
func TestID_UnmarshalJSON_IdUnmarshalError(t *testing.T) {
expectedErr := fmt.Sprintf("Failed to unmarshal ID: length of data "+
"must be %d, length received is %d", ArrIDLen, 0)
id := ID{}
err := id.UnmarshalJSON([]byte("\"\""))
if err == nil || !strings.Contains(err.Error(), expectedErr) {
t.Errorf("UnmarshalJSON failed to return the expected error for "+
"invalid ID.\nexpected: %s\nreceived: %+v", expectedErr, err)
}
}
// Tests that NewRandomID returns the expected IDs for a given PRNG.
func TestNewRandomID_Consistency(t *testing.T) {
prng := rand.New(rand.NewSource(42))
......@@ -599,3 +644,19 @@ func (prng *alphaNumericPRNG) Read(p []byte) (n int, err error) {
return len(p), nil
}
}
// Generates a byte slice of the specified length containing random numbers.
func rngBytes(length int, seed int64, t *testing.T) []byte {
prng := rand.New(rand.NewSource(seed))
// Create new byte slice of the correct size
idBytes := make([]byte, length)
// Create random bytes
_, err := prng.Read(idBytes)
if err != nil {
t.Fatalf("Failed to generate random bytes: %+v", err)
}
return idBytes
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment