Skip to content

Commit

Permalink
Check uniqueness of resources is now opt-in (#61)
Browse files Browse the repository at this point in the history
* Set optional the check uniqueness

* Include unique option

* Inject marshal options
  • Loading branch information
ecdatadog authored Jan 13, 2025
1 parent 326e1d5 commit 6daad4d
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 11 deletions.
15 changes: 12 additions & 3 deletions marshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ func init() {
type Marshaler struct {
meta any
includeJSONAPI bool
checkUniqueness bool
jsonAPImeta any
included []any
link *Link
Expand Down Expand Up @@ -50,6 +51,13 @@ func MarshalJSONAPI(meta any) MarshalOption {
}
}

// MarshallCheckUniqueness enables checking for unique resources during marshaling.
func MarshallCheckUniqueness() MarshalOption {
return func(m *Marshaler) {
m.checkUniqueness = true
}
}

// MarshalInclude includes the json:api encoding of v within Document.Included creating a compound document as defined by https://jsonapi.org/format/#document-compound-documents.
func MarshalInclude(v ...any) MarshalOption {
return func(m *Marshaler) {
Expand Down Expand Up @@ -204,9 +212,10 @@ func makeDocument(v any, m *Marshaler, isRelationship bool) (*document, error) {
}
d.Included = append(d.Included, ro)
}

if ok := d.verifyResourceUniqueness(); !ok {
return nil, ErrNonuniqueResource
if m.checkUniqueness {
if ok := d.verifyResourceUniqueness(); !ok {
return nil, ErrNonuniqueResource
}
}
// if we got any included data, verify full-linkage of this compound document.
if err := d.verifyFullLinkage(false); err != nil {
Expand Down
10 changes: 6 additions & 4 deletions marshal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ func TestMarshal(t *testing.T) {
given any
expect string
expectError error
opts []MarshalOption
}{
{
description: "nil",
Expand Down Expand Up @@ -86,6 +87,7 @@ func TestMarshal(t *testing.T) {
given: articlesAA,
expect: "",
expectError: ErrNonuniqueResource,
opts: []MarshalOption{MarshallCheckUniqueness()},
}, {
description: "[]*Article",
given: articlesABPtr,
Expand Down Expand Up @@ -285,11 +287,11 @@ func TestMarshal(t *testing.T) {

for i, tc := range tests {
tc := tc
t.Run(fmt.Sprintf("%02d", i), func(t *testing.T) {
t.Run(fmt.Sprintf("%02d - %s", i, tc.description), func(t *testing.T) {
t.Parallel()
t.Log(tc.description)

actual, err := Marshal(tc.given)
actual, err := Marshal(tc.given, tc.opts...)
if tc.expectError != nil {
is.EqualError(t, tc.expectError, err)
is.Nil(t, actual)
Expand Down Expand Up @@ -592,7 +594,7 @@ func TestMarshalRelationships(t *testing.T) {
}, {
description: "with related nonunique comments",
given: &articleRelatedNonuniqueComments,
marshalOptions: nil,
marshalOptions: []MarshalOption{MarshallCheckUniqueness()},
expect: "",
expectError: ErrNonuniqueResource,
}, {
Expand Down Expand Up @@ -641,7 +643,7 @@ func TestMarshalRelationships(t *testing.T) {

for i, tc := range tests {
tc := tc
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
t.Run(fmt.Sprintf("%d - %s", i, tc.description), func(t *testing.T) {
t.Parallel()
t.Log(tc.description)

Expand Down
14 changes: 12 additions & 2 deletions unmarshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
type Unmarshaler struct {
unmarshalMeta bool
unmarshalLinks bool
checkUniqueness bool
meta any
links *Link
memberNameValidationMode MemberNameValidationMode
Expand All @@ -35,6 +36,13 @@ func UnmarshalLinks(link *Link) UnmarshalOption {
}
}

// UnmarshalCheckUniqueness enables checking for unique resources during unmarshaling.
func UnmarshalCheckUniqueness() UnmarshalOption {
return func(m *Unmarshaler) {
m.checkUniqueness = true
}
}

// UnmarshalSetNameValidation enables a given level of document member name validation.
func UnmarshalSetNameValidation(mode MemberNameValidationMode) UnmarshalOption {
return func(m *Unmarshaler) {
Expand Down Expand Up @@ -88,8 +96,10 @@ func Unmarshal(data []byte, v any, opts ...UnmarshalOption) (err error) {
}

func (d *document) unmarshal(v any, m *Unmarshaler) (err error) {
if ok := d.verifyResourceUniqueness(); !ok {
return ErrNonuniqueResource
if m.checkUniqueness {
if ok := d.verifyResourceUniqueness(); !ok {
return ErrNonuniqueResource
}
}
// verify full-linkage in-case this is a compound document
if err = d.verifyFullLinkage(true); err != nil {
Expand Down
4 changes: 2 additions & 2 deletions unmarshal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func TestUnmarshal(t *testing.T) {
given: articlesABNonuniqueData,
do: func(body []byte) (any, error) {
var a []Article
err := Unmarshal(body, &a)
err := Unmarshal(body, &a, UnmarshalCheckUniqueness())
return a, err
},
expect: ([]Article)(nil),
Expand Down Expand Up @@ -430,7 +430,7 @@ func TestUnmarshal(t *testing.T) {
given: articleRelatedNonuniqueLinkage,
do: func(body []byte) (any, error) {
var a ArticleRelated
err := Unmarshal(body, &a)
err := Unmarshal(body, &a, UnmarshalCheckUniqueness())
return a, err
},
expect: ArticleRelated{},
Expand Down

0 comments on commit 6daad4d

Please sign in to comment.