Skip to content

Commit 448279a

Browse files
committed
Don't raise error when an invalid choice node is decoded
1 parent 9c90a4f commit 448279a

File tree

2 files changed

+106
-47
lines changed

2 files changed

+106
-47
lines changed

request.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,6 @@ var (
3232
ErrUnknownFieldNumberType = errors.New("The struct field was not of a known number type")
3333
// ErrInvalidType is returned when the given type is incompatible with the expected type.
3434
ErrInvalidType = errors.New("Invalid type provided") // I wish we used punctuation.
35-
// ErrBadJSONAPIJoinStruct is returned when the polyrelation type did not contain
36-
// an appropriate join type to contain the required jsonapi node.
37-
ErrBadJSONAPIJoinStruct = errors.New("Invalid join struct for polymorphic relation field")
3835
)
3936

4037
// ErrUnsupportedPtrType is returned when the Struct field was a pointer but
@@ -245,8 +242,11 @@ func unmarshalNodeMaybeChoice(m *reflect.Value, data *Node, annotation string, c
245242
if annotation == annotationPolyRelation {
246243
c, ok := choiceTypeMapping[data.Type]
247244
if !ok {
248-
// There is no valid join field to assign this type of relation.
249-
return ErrBadJSONAPIJoinStruct
245+
// If there is no valid choice field to assign this type of relation,
246+
// this shouldn't necessarily be an error because a newer version of
247+
// the API could be communicating with an older version of the client
248+
// library, in which case all choice variants would be nil.
249+
return nil
250250
}
251251
choiceElem = &c
252252
actualModel = reflect.New(choiceElem.Type)

request_test.go

Lines changed: 101 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -622,45 +622,6 @@ type OneOfMedia struct {
622622
Video *Video
623623
}
624624

625-
var polySamplePayload = `{
626-
"data": {
627-
"type": "blogs",
628-
"id": "3",
629-
"attributes": {
630-
"title": "Hello, World"
631-
},
632-
"relationships": {
633-
"hero-media": {
634-
"data": {
635-
"type": "videos",
636-
"id": "1",
637-
"attributes": {
638-
"captions": "It's Awesome!"
639-
}
640-
}
641-
},
642-
"media": {
643-
"data": [
644-
{
645-
"type": "images",
646-
"id": "1",
647-
"attributes": {
648-
"src": "/media/clear1x1.gif"
649-
}
650-
},
651-
{
652-
"type": "videos",
653-
"id": "2",
654-
"attributes": {
655-
"captions": "Oh, I didn't see you there"
656-
}
657-
}
658-
]
659-
}
660-
}
661-
}
662-
}`
663-
664625
func Test_UnmarshalPayload_polymorphicRelations(t *testing.T) {
665626
type pointerToOne struct {
666627
ID int `jsonapi:"primary,blogs"`
@@ -669,7 +630,58 @@ func Test_UnmarshalPayload_polymorphicRelations(t *testing.T) {
669630
Media []*OneOfMedia `jsonapi:"polyrelation,media,omitempty"`
670631
}
671632

672-
in := bytes.NewReader([]byte(polySamplePayload))
633+
in := bytes.NewReader([]byte(`{
634+
"data": {
635+
"type": "blogs",
636+
"id": "3",
637+
"attributes": {
638+
"title": "Hello, World"
639+
},
640+
"relationships": {
641+
"hero-media": {
642+
"data": {
643+
"type": "videos",
644+
"id": "1"
645+
}
646+
},
647+
"media": {
648+
"data": [
649+
{
650+
"type": "images",
651+
"id": "1"
652+
},
653+
{
654+
"type": "videos",
655+
"id": "2"
656+
}
657+
]
658+
}
659+
}
660+
},
661+
"included": [
662+
{
663+
"type": "videos",
664+
"id": "1",
665+
"attributes": {
666+
"captions": "It's Awesome!"
667+
}
668+
},
669+
{
670+
"type": "images",
671+
"id": "1",
672+
"attributes": {
673+
"src": "/media/clear1x1.gif"
674+
}
675+
},
676+
{
677+
"type": "videos",
678+
"id": "2",
679+
"attributes": {
680+
"captions": "Oh, I didn't see you there"
681+
}
682+
}
683+
]
684+
}`))
673685
out := new(pointerToOne)
674686

675687
if err := UnmarshalPayload(in, out); err != nil {
@@ -688,12 +700,59 @@ func Test_UnmarshalPayload_polymorphicRelations(t *testing.T) {
688700
t.Errorf("expected Hero to be the expected video relation but got %+v", out.Hero.Video)
689701
}
690702

703+
// Unmarshals included records
691704
if out.Media[0].Image == nil || out.Media[0].Image.Src != "/media/clear1x1.gif" {
692-
t.Errorf("expected Media 0 to be the expected image relation but got %+v", out.Media[0])
705+
t.Errorf("expected Media 0 to be the expected image relation but got %+v", out.Media[0].Image)
693706
}
694707

695708
if out.Media[1].Video == nil || out.Media[1].Video.Captions != "Oh, I didn't see you there" {
696-
t.Errorf("expected Media 0 to be the expected video relation but got %+v", out.Media[1])
709+
t.Errorf("expected Media 1 to be the expected video relation but got %+v", out.Media[1].Video)
710+
}
711+
}
712+
713+
func Test_UnmarshalPayload_polymorphicRelations_no_choice(t *testing.T) {
714+
type pointerToOne struct {
715+
ID int `jsonapi:"primary,blogs"`
716+
Title string `jsonapi:"attr,title"`
717+
Hero *OneOfMedia `jsonapi:"polyrelation,hero-media,omitempty"`
718+
}
719+
720+
in := bytes.NewReader([]byte(`{
721+
"data": {
722+
"type": "blogs",
723+
"id": "3",
724+
"attributes": {
725+
"title": "Hello, World"
726+
},
727+
"relationships": {
728+
"hero-media": {
729+
"data": {
730+
"type": "absolutely-not",
731+
"id": "1",
732+
"attributes": {
733+
"captions": "It's Awesome!"
734+
}
735+
}
736+
}
737+
}
738+
}
739+
}`))
740+
out := new(pointerToOne)
741+
742+
if err := UnmarshalPayload(in, out); err != nil {
743+
t.Fatal(err)
744+
}
745+
746+
if out.Title != "Hello, World" {
747+
t.Errorf("expected Title %q but got %q", "Hello, World", out.Title)
748+
}
749+
750+
if out.Hero == nil {
751+
t.Fatal("expected Hero to not be nil")
752+
}
753+
754+
if out.Hero.Image != nil || out.Hero.Video != nil {
755+
t.Fatal("expected both Hero fields to be nil")
697756
}
698757
}
699758

0 commit comments

Comments
 (0)