json-api 0.1.1.0 → 0.1.1.1
raw patch · 9 files changed
+82/−33 lines, 9 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Network.JSONApi: List :: [Resource a] -> ResourceData a
- Network.JSONApi: Singleton :: (Resource a) -> ResourceData a
- Network.JSONApi: data ResourceData a
- Network.JSONApi: toLinks :: [(Rel, URL)] -> Links
- Network.JSONApi.Document: List :: [Resource a] -> ResourceData a
- Network.JSONApi.Document: Singleton :: (Resource a) -> ResourceData a
- Network.JSONApi.Document: data ResourceData a
- Network.JSONApi.Link: toLinks :: [(Rel, URL)] -> Links
+ Network.JSONApi: data Included
+ Network.JSONApi: mkCompoundDocument :: ResourcefulEntity a => [a] -> Maybe Links -> Maybe Meta -> Included -> Document a
+ Network.JSONApi: mkIncludedResource :: ResourcefulEntity a => a -> Included
+ Network.JSONApi: mkLinks :: [(Rel, URL)] -> Links
+ Network.JSONApi.Document: data Included
+ Network.JSONApi.Document: instance GHC.Base.Monoid Network.JSONApi.Document.Included
+ Network.JSONApi.Document: instance GHC.Show.Show Network.JSONApi.Document.Included
+ Network.JSONApi.Document: mkCompoundDocument :: ResourcefulEntity a => [a] -> Maybe Links -> Maybe Meta -> Included -> Document a
+ Network.JSONApi.Document: mkIncludedResource :: ResourcefulEntity a => a -> Included
+ Network.JSONApi.Link: mkLinks :: [(Rel, URL)] -> Links
- Network.JSONApi: mkDocument :: ResourcefulEntity a => [a] -> Maybe Links -> Maybe Meta -> [Value] -> Document a
+ Network.JSONApi: mkDocument :: ResourcefulEntity a => [a] -> Maybe Links -> Maybe Meta -> Document a
- Network.JSONApi.Document: mkDocument :: ResourcefulEntity a => [a] -> Maybe Links -> Maybe Meta -> [Value] -> Document a
+ Network.JSONApi.Document: mkDocument :: ResourcefulEntity a => [a] -> Maybe Links -> Maybe Meta -> Document a
Files
- json-api.cabal +1/−1
- src/Network/JSONApi.hs +4/−4
- src/Network/JSONApi/Document.hs +58/−9
- src/Network/JSONApi/Link.hs +3/−3
- test/Network/JSONApi/DocumentSpec.hs +11/−9
- test/Network/JSONApi/ErrorSpec.hs +1/−1
- test/Network/JSONApi/MetaSpec.hs +1/−1
- test/Network/JSONApi/ResourceSpec.hs +2/−4
- test/TestHelpers.hs +1/−1
json-api.cabal view
@@ -1,5 +1,5 @@ name: json-api-version: 0.1.1.0+version: 0.1.1.1 homepage: https://github.com/toddmohney/json-api bug-reports: https://github.com/toddmohney/json-api/issues license: MIT
src/Network/JSONApi.hs view
@@ -1,13 +1,11 @@ {- | Entry-point module for this package.--Contains representations of the top-level JSON-API document structure. -} module Network.JSONApi ( D.Document , D.ErrorDocument (..)+ , D.Included , E.Error (..)- , D.ResourceData (..) , R.Relationship , R.Resource (..) , R.ResourcefulEntity (..)@@ -15,9 +13,11 @@ , L.Links , M.Meta (..) , M.MetaObject (..)- , L.toLinks+ , L.mkLinks , R.mkRelationship , D.mkDocument+ , D.mkCompoundDocument+ , D.mkIncludedResource , M.mkMeta ) where
src/Network/JSONApi/Document.hs view
@@ -1,14 +1,14 @@ {- |-Entry-point module for this package.- Contains representations of the top-level JSON-API document structure. -} module Network.JSONApi.Document-( Document-, ErrorDocument (..)-, ResourceData (..)-, mkDocument-) where+ ( Document+ , ErrorDocument (..)+ , Included+ , mkDocument+ , mkCompoundDocument+ , mkIncludedResource+ ) where import Control.Monad (mzero) import Data.Aeson@@ -20,6 +20,7 @@ , (.:?) ) import qualified Data.Aeson as AE+import Data.Monoid import qualified GHC.Generics as G import qualified Network.JSONApi.Error as E import Network.JSONApi.Link as L@@ -66,21 +67,69 @@ return (Document d l m i) {- |+The @Included@ type is an abstraction used to constrain the "included"+section of the Document to JSON serializable Resource objects while+enabling a heterogeneous list of Resource types.++No data constructors for this type are exported as we need to+constrain the @Value@ to a heterogeneous list of Resource types.+See @mkIncludedResource@ for creating @Included@ types.+-}+data Included = Included [Value]+ deriving (Show)++instance Monoid Included where+ mempty = Included []+ mappend (Included as) (Included bs) = Included (as <> bs)++{- | Constructor function for the Document data type.++See @mkCompoundDocument@ for constructing compound Document+including 'side-loaded' resources -} mkDocument :: ResourcefulEntity a => [a] -> Maybe Links -> Maybe Meta- -> [Value] -> Document a-mkDocument res links meta included =+mkDocument res links meta = Document { _data = toResourceData res , _links = links , _meta = meta+ , _included = []+ }++{- |+Constructor function for the Document data type.+See @mkIncludedResource@ for constructing the @Included@ type.++Supports building compound documents+<http://jsonapi.org/format/#document-compound-documents>+-}+mkCompoundDocument :: ResourcefulEntity a =>+ [a]+ -> Maybe Links+ -> Maybe Meta+ -> Included+ -> Document a+mkCompoundDocument res links meta (Included included) =+ Document+ { _data = toResourceData res+ , _links = links+ , _meta = meta , _included = included }++{- |+Constructor function for the Document data type.++Supports building compound documents+<http://jsonapi.org/format/#document-compound-documents>+-}+mkIncludedResource :: ResourcefulEntity a => a -> Included+mkIncludedResource res = Included [AE.toJSON . R.toResource $ res] toResourceData :: ResourcefulEntity a => [a] -> ResourceData a toResourceData (r:[]) = Singleton (R.toResource r)
src/Network/JSONApi/Link.hs view
@@ -7,7 +7,7 @@ ( Links , Rel , Href-, toLinks+, mkLinks ) where import Data.Aeson (ToJSON, FromJSON)@@ -41,8 +41,8 @@ {- | Constructor function for building Links -}-toLinks :: [(Rel, URL)] -> Links-toLinks = Links . Map.fromList . map buildLink+mkLinks :: [(Rel, URL)] -> Links+mkLinks = Links . Map.fromList . map buildLink buildLink :: (Rel, URL) -> (Rel, Href) buildLink (key, url) = (key, pack (exportURL url))
test/Network/JSONApi/DocumentSpec.hs view
@@ -5,10 +5,11 @@ import qualified Data.Aeson as AE import qualified Data.Aeson.Lens as Lens import Data.ByteString.Lazy.Char8 (ByteString)-{- import qualified Data.ByteString.Lazy.Char8 as BS -}+import qualified Data.ByteString.Lazy.Char8 as BS import Data.Either (isRight) import Data.Maybe-import Network.JSONApi.Document+import Data.Monoid+import Network.JSONApi import TestHelpers import Test.Hspec @@ -20,7 +21,7 @@ describe "JSON serialization" $ do it "JSON encodes/decodes a singleton resource" $ do -- TODO: test the main resource actually is a singleton- let jsonApiObj = mkDocument [testObject] Nothing Nothing []+ let jsonApiObj = mkDocument [testObject] Nothing Nothing let encodedJson = encodeDocumentObject jsonApiObj let decodedJson = decodeDocumentObject encodedJson {- putStrLn (BS.unpack encodedJson) -}@@ -29,7 +30,7 @@ it "JSON encodes/decodes a list of resources" $ do -- TODO: test the main resource actually is a list- let jsonApiObj = mkDocument [testObject, testObject2] Nothing Nothing []+ let jsonApiObj = mkDocument [testObject, testObject2] Nothing Nothing let encodedJson = encodeDocumentObject jsonApiObj let decodedJson = decodeDocumentObject encodedJson {- putStrLn (BS.unpack encodedJson) -}@@ -37,7 +38,7 @@ isRight decodedJson `shouldBe` True it "contains the allowable top-level keys" $ do- let jsonApiObj = mkDocument [testObject] Nothing Nothing []+ let jsonApiObj = mkDocument [testObject] Nothing Nothing let encodedJson = encodeDocumentObject jsonApiObj let dataObject = encodedJson ^? Lens.key "data" let linksObject = encodedJson ^? Lens.key "links"@@ -49,7 +50,7 @@ isJust includedObject `shouldBe` True it "allows an optional top-level links object" $ do- let jsonApiObj = mkDocument [testObject] (Just linksObj) Nothing []+ let jsonApiObj = mkDocument [testObject] (Just linksObj) Nothing let encodedJson = encodeDocumentObject jsonApiObj let decodedJson = decodeDocumentObject encodedJson -- putStrLn (BS.unpack encodedJson)@@ -57,7 +58,7 @@ isRight decodedJson `shouldBe` True it "allows an optional top-level meta object" $ do- let jsonApiObj = mkDocument [testObject] Nothing (Just testMetaObj) []+ let jsonApiObj = mkDocument [testObject] Nothing (Just testMetaObj) let encodedJson = encodeDocumentObject jsonApiObj let decodedJson = decodeDocumentObject encodedJson -- putStrLn (BS.unpack encodedJson)@@ -65,10 +66,11 @@ isRight decodedJson `shouldBe` True it "allows a heterogeneous list of related resources" $ do- let jsonApiObj = mkDocument [testObject] Nothing Nothing [AE.toJSON (toResource' testObject Nothing Nothing), AE.toJSON (toResource' otherTestObject Nothing Nothing)]+ let includedResources = (mkIncludedResource testObject) <> (mkIncludedResource testObject2)+ let jsonApiObj = mkCompoundDocument [testObject] Nothing Nothing includedResources let encodedJson = encodeDocumentObject jsonApiObj let decodedJson = decodeDocumentObject encodedJson- {- putStrLn (BS.unpack encodedJson) -}+ putStrLn (BS.unpack encodedJson) {- putStrLn $ show decodedJson -} isRight decodedJson `shouldBe` True
test/Network/JSONApi/ErrorSpec.hs view
@@ -4,7 +4,7 @@ import qualified Data.ByteString.Lazy.Char8 as BS import Data.Default (def) import Data.Maybe-import Network.JSONApi.Error+import Network.JSONApi import Prelude hiding (id) import TestHelpers (prettyEncode) import Test.Hspec
test/Network/JSONApi/MetaSpec.hs view
@@ -8,7 +8,7 @@ import Data.Monoid ((<>)) import Data.Text (Text) import GHC.Generics (Generic)-import Network.JSONApi.Meta+import Network.JSONApi import TestHelpers (prettyEncode) import Test.Hspec
test/Network/JSONApi/ResourceSpec.hs view
@@ -8,9 +8,7 @@ import Data.Maybe (isJust, fromJust) import Data.Text (Text, pack) import qualified GHC.Generics as G-import Network.JSONApi.Resource-import Network.JSONApi.Link-import Network.JSONApi.Meta+import Network.JSONApi import Network.URL (URL, importURL) import TestHelpers (prettyEncode) import Test.Hspec@@ -55,7 +53,7 @@ myResourceLinks :: Links myResourceLinks =- toLinks [ ("self", toURL "/me")+ mkLinks [ ("self", toURL "/me") , ("related", toURL "/tacos/4") ]
test/TestHelpers.hs view
@@ -79,7 +79,7 @@ Nothing linksObj :: Links-linksObj = toLinks [ ("self", toURL "/things/1")+linksObj = mkLinks [ ("self", toURL "/things/1") , ("related", toURL "http://some.domain.com/other/things/1") ]