module Network.JSONApi.Resource
( Identifier (..)
, Resource (..)
, ResourcefulEntity (..)
, Relationship
, mkRelationship
) where
import Data.Aeson (ToJSON, FromJSON, (.=), (.:), (.:?))
import qualified Data.Aeson as AE
import qualified Data.Aeson.Types as AE
import Data.Map (Map)
import Data.Text (Text)
import qualified GHC.Generics as G
import Network.JSONApi.Link (Links)
import Network.JSONApi.Meta (Meta)
import Prelude hiding (id)
data Resource a = Resource
{ getIdentifier :: Identifier
, getResource :: a
, getLinks :: Maybe Links
, getMetaData :: Maybe Meta
, getRelationships :: Maybe (Map Text Relationship)
} deriving (Show, Eq, G.Generic)
instance (ToJSON a) => ToJSON (Resource a) where
toJSON (Resource (Identifier resId resType) resObj linksObj metaObj rels) =
AE.object [ "id" .= resId
, "type" .= resType
, "attributes" .= resObj
, "links" .= linksObj
, "meta" .= metaObj
, "relationships" .= rels
]
instance (FromJSON a) => FromJSON (Resource a) where
parseJSON = AE.withObject "resourceObject" $ \v -> do
id <- v .: "id"
typ <- v .: "type"
attrs <- v .: "attributes"
links <- v .:? "links"
meta <- v .:? "meta"
rels <- v .:? "relationships"
return $ Resource (Identifier id typ) attrs links meta rels
class (ToJSON a, FromJSON a) => ResourcefulEntity a where
resourceIdentifier :: a -> Text
resourceType :: a -> Text
resourceLinks :: a -> Maybe Links
resourceMetaData :: a -> Maybe Meta
resourceRelationships :: a -> Maybe (Map Text Relationship)
fromResource :: Resource a -> a
fromResource = getResource
toResource :: a -> Resource a
toResource a =
Resource
(Identifier (resourceIdentifier a) (resourceType a))
a
(resourceLinks a)
(resourceMetaData a)
(resourceRelationships a)
data Relationship = Relationship
{ _data :: Maybe Identifier
, _links :: Maybe Links
} deriving (Show, Eq, G.Generic)
instance ToJSON Relationship where
toJSON = AE.genericToJSON
AE.defaultOptions { AE.fieldLabelModifier = drop 1 }
instance FromJSON Relationship where
parseJSON = AE.genericParseJSON
AE.defaultOptions { AE.fieldLabelModifier = drop 1 }
mkRelationship :: Maybe Identifier -> Maybe Links -> Maybe Relationship
mkRelationship Nothing Nothing = Nothing
mkRelationship resId links = Just $ Relationship resId links
data Identifier = Identifier
{ _id :: Text
, _type :: Text
} deriving (Show, Eq, G.Generic)
instance ToJSON Identifier where
toJSON = AE.genericToJSON
AE.defaultOptions { AE.fieldLabelModifier = drop 1 }
instance FromJSON Identifier where
parseJSON = AE.genericParseJSON
AE.defaultOptions { AE.fieldLabelModifier = drop 1 }