Skip to content

Commit a21f139

Browse files
ryanubersharpner
authored andcommitted
Support links with null values (#313)
* Support links with null values
1 parent 69d7202 commit a21f139

File tree

4 files changed

+26
-2
lines changed

4 files changed

+26
-2
lines changed

jsonapi/data_structs.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ type Link struct {
5858
// UnmarshalJSON marshals a string value into the Href field or marshals an
5959
// object value into the whole struct.
6060
func (l *Link) UnmarshalJSON(payload []byte) error {
61+
// Links may be null in certain cases, mainly noted in the JSONAPI spec
62+
// with pagination links (http://jsonapi.org/format/#fetching-pagination).
63+
if len(payload) == 4 && string(payload) == "null" {
64+
return nil
65+
}
66+
6167
if bytes.HasPrefix(payload, stringSuffix) {
6268
return json.Unmarshal(payload, &l.Href)
6369
}
@@ -84,6 +90,9 @@ func (l *Link) UnmarshalJSON(payload []byte) error {
8490
// MarshalJSON returns the JSON encoding of only the Href field if the Meta
8591
// field is empty, otherwise it marshals the whole struct.
8692
func (l Link) MarshalJSON() ([]byte, error) {
93+
if l.Empty() {
94+
return json.Marshal(nil)
95+
}
8796
if len(l.Meta) == 0 {
8897
return json.Marshal(l.Href)
8998
}
@@ -93,6 +102,11 @@ func (l Link) MarshalJSON() ([]byte, error) {
93102
})
94103
}
95104

105+
// Empty returns true if the link has no href and no metadata.
106+
func (l Link) Empty() bool {
107+
return len(l.Meta) == 0 && l.Href == ""
108+
}
109+
96110
// Links contains a map of custom Link objects as given by an element.
97111
type Links map[string]Link
98112

jsonapi/data_structs_test.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,14 @@ var _ = Describe("JSONAPI Struct tests", func() {
208208
Expect(target).To(Equal(expected))
209209
})
210210

211+
It("unmarshals from null", func() {
212+
expected := Link{}
213+
target := Link{}
214+
err := json.Unmarshal([]byte(`null`), &target)
215+
Expect(err).ToNot(HaveOccurred())
216+
Expect(target).To(Equal(expected))
217+
})
218+
211219
It("unmarshals with an error when href is missing", func() {
212220
err := json.Unmarshal([]byte(`{}`), &Link{})
213221
Expect(err).To(HaveOccurred())
@@ -224,7 +232,7 @@ var _ = Describe("JSONAPI Struct tests", func() {
224232
})
225233

226234
It("unmarshals with an error for wrong types", func() {
227-
badPayloads := []string{`null`, `13`, `[]`}
235+
badPayloads := []string{`13`, `[]`}
228236
for _, payload := range badPayloads {
229237
err := json.Unmarshal([]byte(payload), &Link{})
230238
Expect(err).To(HaveOccurred())

jsonapi/fixtures_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,8 @@ func (n CustomLinksPost) GetName() string {
489489

490490
func (n CustomLinksPost) GetCustomLinks(base string) Links {
491491
return Links{
492-
"someLink": Link{Href: base + `/someLink`},
492+
"nothingInHere": Link{},
493+
"someLink": Link{Href: base + `/someLink`},
493494
"otherLink": Link{
494495
Href: base + `/otherLink`,
495496
Meta: Meta{

jsonapi/marshal_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ var _ = Describe("Marshalling", func() {
232232
"id": "someID",
233233
"attributes": {},
234234
"links": {
235+
"nothingInHere": null,
235236
"someLink": "http://my.domain/v1/posts/someID/someLink",
236237
"otherLink": {
237238
"href": "http://my.domain/v1/posts/someID/otherLink",

0 commit comments

Comments
 (0)