@@ -199,6 +199,7 @@ func (b Banana) GetID() string {
199199type User struct {
200200 ID string `jsonapi:"-"`
201201 Name string
202+ Info string
202203}
203204
204205func (u User ) GetID () string {
@@ -524,6 +525,7 @@ var _ = Describe("RestHandler", func() {
524525 "type" : "users" ,
525526 "attributes" : map [string ]interface {}{
526527 "name" : "Dieter" ,
528+ "info" : "" ,
527529 },
528530 },
529531 {
@@ -650,7 +652,8 @@ var _ = Describe("RestHandler", func() {
650652 "id": "1",
651653 "type": "users",
652654 "attributes": {
653- "name": "Dieter"
655+ "name": "Dieter",
656+ "info": ""
654657 }
655658 }}` ))
656659 })
@@ -1587,4 +1590,205 @@ var _ = Describe("RestHandler", func() {
15871590 Expect (rec .Body .Bytes ()).To (ContainSubstring (expected ))
15881591 })
15891592 })
1593+
1594+ Context ("Sparse Fieldsets" , func () {
1595+ var (
1596+ source * fixtureSource
1597+ api * API
1598+ rec * httptest.ResponseRecorder
1599+ )
1600+
1601+ BeforeEach (func () {
1602+ author := User {ID : "666" , Name : "Tester" , Info : "Is curious about testing" }
1603+ source = & fixtureSource {map [string ]* Post {
1604+ "1" : {ID : "1" , Title : "Nice Post" , Value : null .FloatFrom (13.37 ), Author : & author },
1605+ }, false }
1606+ api = NewAPI ("" )
1607+ api .AddResource (Post {}, source )
1608+ rec = httptest .NewRecorder ()
1609+ })
1610+
1611+ It ("only returns requested post fields for single post" , func () {
1612+ req , err := http .NewRequest ("GET" , "/posts/1?fields[posts]=title,value" , nil )
1613+ Expect (err ).ToNot (HaveOccurred ())
1614+ api .Handler ().ServeHTTP (rec , req )
1615+ Expect (rec .Code ).To (Equal (http .StatusOK ))
1616+ Expect (rec .Body .Bytes ()).To (MatchJSON (`
1617+ {"data": {
1618+ "id": "1",
1619+ "type": "posts",
1620+ "attributes": {
1621+ "title": "Nice Post",
1622+ "value": 13.37
1623+ },
1624+ "relationships": {
1625+ "author": {
1626+ "data": {
1627+ "id": "666",
1628+ "type": "users"
1629+ },
1630+ "links": {
1631+ "related": "/posts/1/author",
1632+ "self": "/posts/1/relationships/author"
1633+ }
1634+ },
1635+ "bananas": {
1636+ "data": [],
1637+ "links": {
1638+ "related": "/posts/1/bananas",
1639+ "self": "/posts/1/relationships/bananas"
1640+ }
1641+ },
1642+ "comments": {
1643+ "data": [],
1644+ "links": {
1645+ "related": "/posts/1/comments",
1646+ "self": "/posts/1/relationships/comments"
1647+ }
1648+ }
1649+ }
1650+ },
1651+ "included": [
1652+ {
1653+ "attributes": {
1654+ "info": "Is curious about testing",
1655+ "name": "Tester"
1656+ },
1657+ "id": "666",
1658+ "type": "users"
1659+ }
1660+ ]
1661+ }` ))
1662+ })
1663+
1664+ It ("FindOne: only returns requested post field for single post and includes" , func () {
1665+ req , err := http .NewRequest ("GET" , "/posts/1?fields[posts]=title&fields[users]=name" , nil )
1666+ Expect (err ).ToNot (HaveOccurred ())
1667+ api .Handler ().ServeHTTP (rec , req )
1668+ Expect (rec .Code ).To (Equal (http .StatusOK ))
1669+ Expect (rec .Body .Bytes ()).To (MatchJSON (`
1670+ {"data": {
1671+ "id": "1",
1672+ "type": "posts",
1673+ "attributes": {
1674+ "title": "Nice Post"
1675+ },
1676+ "relationships": {
1677+ "author": {
1678+ "data": {
1679+ "id": "666",
1680+ "type": "users"
1681+ },
1682+ "links": {
1683+ "related": "/posts/1/author",
1684+ "self": "/posts/1/relationships/author"
1685+ }
1686+ },
1687+ "bananas": {
1688+ "data": [],
1689+ "links": {
1690+ "related": "/posts/1/bananas",
1691+ "self": "/posts/1/relationships/bananas"
1692+ }
1693+ },
1694+ "comments": {
1695+ "data": [],
1696+ "links": {
1697+ "related": "/posts/1/comments",
1698+ "self": "/posts/1/relationships/comments"
1699+ }
1700+ }
1701+ }
1702+ },
1703+ "included": [
1704+ {
1705+ "attributes": {
1706+ "name": "Tester"
1707+ },
1708+ "id": "666",
1709+ "type": "users"
1710+ }
1711+ ]
1712+ }` ))
1713+ })
1714+
1715+ It ("FindAll: only returns requested post field for single post and includes" , func () {
1716+ req , err := http .NewRequest ("GET" , "/posts?fields[posts]=title&fields[users]=name" , nil )
1717+ Expect (err ).ToNot (HaveOccurred ())
1718+ api .Handler ().ServeHTTP (rec , req )
1719+ Expect (rec .Code ).To (Equal (http .StatusOK ))
1720+ Expect (rec .Body .Bytes ()).To (MatchJSON (`
1721+ {"data": [{
1722+ "id": "1",
1723+ "type": "posts",
1724+ "attributes": {
1725+ "title": "Nice Post"
1726+ },
1727+ "relationships": {
1728+ "author": {
1729+ "data": {
1730+ "id": "666",
1731+ "type": "users"
1732+ },
1733+ "links": {
1734+ "related": "/posts/1/author",
1735+ "self": "/posts/1/relationships/author"
1736+ }
1737+ },
1738+ "bananas": {
1739+ "data": [],
1740+ "links": {
1741+ "related": "/posts/1/bananas",
1742+ "self": "/posts/1/relationships/bananas"
1743+ }
1744+ },
1745+ "comments": {
1746+ "data": [],
1747+ "links": {
1748+ "related": "/posts/1/comments",
1749+ "self": "/posts/1/relationships/comments"
1750+ }
1751+ }
1752+ }
1753+ }],
1754+ "included": [
1755+ {
1756+ "attributes": {
1757+ "name": "Tester"
1758+ },
1759+ "id": "666",
1760+ "type": "users"
1761+ }
1762+ ]
1763+ }` ))
1764+ })
1765+
1766+ It ("Summarize all invalid field query parameters as error" , func () {
1767+ req , err := http .NewRequest ("GET" , "/posts?fields[posts]=title,nonexistent&fields[users]=name,title,fluffy,pink" , nil )
1768+ Expect (err ).ToNot (HaveOccurred ())
1769+ api .Handler ().ServeHTTP (rec , req )
1770+ Expect (rec .Code ).To (Equal (http .StatusBadRequest ))
1771+ error := HTTPError {}
1772+ err = json .Unmarshal (rec .Body .Bytes (), & error )
1773+ Expect (err ).ToNot (HaveOccurred ())
1774+
1775+ expectedError := func (field , objType string ) Error {
1776+ return Error {
1777+ Status : "Bad Request" ,
1778+ Code : codeInvalidQueryFields ,
1779+ Title : fmt .Sprintf (`Field "%s" does not exist for type "%s"` , field , objType ),
1780+ Detail : "Please make sure you do only request existing fields" ,
1781+ Source : & ErrorSource {
1782+ Parameter : fmt .Sprintf ("fields[%s]" , objType ),
1783+ },
1784+ }
1785+ }
1786+
1787+ Expect (error .Errors ).To (HaveLen (4 ))
1788+ Expect (error .Errors ).To (ContainElement (expectedError ("nonexistent" , "posts" )))
1789+ Expect (error .Errors ).To (ContainElement (expectedError ("title" , "users" )))
1790+ Expect (error .Errors ).To (ContainElement (expectedError ("fluffy" , "users" )))
1791+ Expect (error .Errors ).To (ContainElement (expectedError ("pink" , "users" )))
1792+ })
1793+ })
15901794})
0 commit comments