Skip to content

Commit

Permalink
Support node id unmarshalling for custom types
Browse files Browse the repository at this point in the history
  • Loading branch information
hypnoglow committed Apr 27, 2018
1 parent d11604b commit 4309b1d
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 2 deletions.
24 changes: 22 additions & 2 deletions request.go
Original file line number Diff line number Diff line change
Expand Up @@ -542,9 +542,29 @@ func fullNode(n *Node, included *map[string]*Node) *Node {
// assign will take the value specified and assign it to the field; if
// field is expecting a ptr assign will assign a ptr.
func assign(field, value reflect.Value) {
if field.Kind() == reflect.Ptr {
if value.Type().AssignableTo(field.Type()) {
field.Set(value)
return
}

indirectValue := reflect.Indirect(value)
if indirectValue.Type().AssignableTo(field.Type()) {
field.Set(indirectValue)
return
}

// Conversion required.

if field.Kind() == reflect.Ptr {
if value.Kind() == reflect.Ptr {
field.Set(value.Convert(field.Type()))
} else {
// Because field is zero value, we cannot simply field.Elem().Set().
v := reflect.New(field.Type().Elem())
v.Elem().Set(value.Convert(field.Type().Elem()))
field.Set(v)
}
} else {
field.Set(reflect.Indirect(value))
field.Set(reflect.Indirect(value).Convert(field.Type()))
}
}
106 changes: 106 additions & 0 deletions request_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,112 @@ func TestManyPayload_withLinks(t *testing.T) {
}
}

func TestUnmarshalPayloadIDTypeOfString(t *testing.T) {
t.Run("Unmarshal string to value type", func(t *testing.T) {
data := map[string]interface{}{
"data": map[string]interface{}{
"type": "books",
"id": "978-3-16-148410-0",
"attributes": map[string]interface{}{
"title": "Gesammelte Werke in deutscher Sprache",
},
},
}
b, err := json.Marshal(data)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}

type (
IBSN string

Book struct {
ID IBSN `jsonapi:"primary,books"`
Title string `jsonapi:"attr,title"`
}
)

book := &Book{}
if err := UnmarshalPayload(bytes.NewReader(b), book); err != nil {
t.Fatalf("Unexpected error: %v", err)
}

expected := IBSN("978-3-16-148410-0")
if book.ID != expected {
t.Fatalf("Expected book id to be %v but got %v", expected, book.ID)
}
})

t.Run("Unmarshal string to ptr type", func(t *testing.T) {
data := map[string]interface{}{
"data": map[string]interface{}{
"type": "books",
"id": "978-3-16-148410-0",
"attributes": map[string]interface{}{
"title": "Gesammelte Werke in deutscher Sprache",
},
},
}
b, err := json.Marshal(data)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}

type (
IBSN string

Book struct {
ID *IBSN `jsonapi:"primary,books"`
Title string `jsonapi:"attr,title"`
}
)

book := &Book{}
if err := UnmarshalPayload(bytes.NewReader(b), book); err != nil {
t.Fatalf("Unexpected error: %v", err)
}

expected := IBSN("978-3-16-148410-0")
if !reflect.DeepEqual(book.ID, &expected) {
t.Fatalf("Expected book id to be %v but got %v", &expected, book.ID)
}
})

t.Run("Unmarshal nil to ptr type", func(t *testing.T) {
data := map[string]interface{}{
"data": map[string]interface{}{
"type": "books",
"id": nil,
"attributes": map[string]interface{}{
"title": "Gesammelte Werke in deutscher Sprache",
},
},
}
b, err := json.Marshal(data)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}

type (
IBSN string

Book struct {
ID *IBSN `jsonapi:"primary,books"`
Title string `jsonapi:"attr,title"`
}
)

book := &Book{}
if err := UnmarshalPayload(bytes.NewReader(b), book); err != nil {
t.Fatalf("Unexpected error: %v", err)
}

if book.ID != nil {
t.Fatalf("Expected book id to be %v but got %v", nil, book.ID)
}
})
}

func samplePayloadWithoutIncluded() map[string]interface{} {
return map[string]interface{}{
"data": map[string]interface{}{
Expand Down

0 comments on commit 4309b1d

Please sign in to comment.