hasklepias-0.17.0: src/EventData/Aeson.hs
{-|
Module : Functions for Parsing Event data model
Description : Defines FromJSON instances for Events.
Copyright : (c) NoviSci, Inc 2020
License : BSD3
Maintainer : bsaul@novisci.com
-}
{-# OPTIONS_HADDOCK hide #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE FlexibleInstances, OverloadedStrings #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
module EventData.Aeson
( parseEventIntLines
, parseEventDayLines
) where
import Control.Monad
import Data.Aeson ( (.:)
, (.:?)
, FromJSON(parseJSON)
, Value(Array)
, eitherDecode
, withObject
)
import qualified Data.ByteString.Char8 as C
import qualified Data.ByteString.Lazy as B
import Data.Either ( Either(..)
, either
, partitionEithers
)
import Data.Maybe ( fromMaybe )
import Data.Text ( Text )
import Data.Time ( Day )
import Data.Vector ( (!) )
import EventData.Context ( Concept
, Concepts
, Context
, context
, packConcept
, toConcepts
)
import EventData.Context.Domain
import EventData.Core ( Event
, event
)
import IntervalAlgebra ( Interval
, IntervalSizeable
( add
, diff
, moment
)
, beginerval
, parseInterval
)
import Prelude ( ($)
, (<$>)
, (<*>)
, Int
, Ord
, Show
, String
, fmap
, id
, pure
)
instance (FromJSON a, Show a, IntervalSizeable a b) => FromJSON (Interval a) where
parseJSON = withObject "Time" $ \o -> do
t <- o .: "time"
b <- t .: "begin"
e <- t .:? "end"
-- In the case that the end is missing, create a moment
let e2 = fromMaybe (add (moment @a) b) e
let ei = parseInterval b e2
case ei of
Left e -> fail e
Right i -> return i
instance FromJSON Domain where
parseJSON = withObject "Domain" $ \o -> do
domain :: Text <- o .: "domain"
case domain of
"Demographics" -> Demographics <$> o .: "facts"
"Enrollment" -> pure $ Enrollment (EnrollmentFacts ())
_ -> pure (UnimplementedDomain ())
instance FromJSON Concept where
parseJSON c = packConcept <$> parseJSON c
instance FromJSON Concepts where
parseJSON c = toConcepts <$> parseJSON c
instance FromJSON Context where
parseJSON (Array v) = context <$> parseJSON (v ! 5) <*> parseJSON (v ! 4)
instance (FromJSON a, Show a, IntervalSizeable a b) => FromJSON (Event a) where
parseJSON (Array v) = event <$> parseJSON (v ! 5) <*> parseJSON (Array v)
-- | Parse @Event Int@ from json lines.
parseEventLines
:: (FromJSON a, Show a, IntervalSizeable a b)
=> B.ByteString
-> ([String], [Event a])
parseEventLines l = partitionEithers $ fmap
(\x ->
eitherDecode $ B.fromStrict x :: (FromJSON a, Show a, IntervalSizeable a b)
=> Either String (Event a)
)
(C.lines $ B.toStrict l)
-- | Parse @Event Int@ from json lines.
parseEventIntLines
:: (FromJSON a, Show a, IntervalSizeable a b)
=> B.ByteString
-> ([String], [Event a])
parseEventIntLines = parseEventLines
-- | Parse @Event Day@ from json lines.
parseEventDayLines
:: (FromJSON a, Show a, IntervalSizeable a b)
=> B.ByteString
-> ([String], [Event a])
parseEventDayLines = parseEventLines