{-# LANGUAGE CPP #-}
{-# LANGUAGE DerivingVia #-}
#if MIN_VERSION_aeson(2,2,0)
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE UndecidableInstances #-}
#endif
module HaskellWorks.Data.Aeson
( JsonEndo(..)
, WithJsonKeyValues(..)
, ToJsonKeyValues(..)
, objectWithoutNulls
, readJson
, objectEndo
, (.?=)
, (.!=)
) where
import Data.Aeson (pairs, object, KeyValue((.=)), ToJSON(toJSON, toEncoding), Series, Value(Null))
import Data.Aeson.Encoding (Encoding)
import Data.Aeson.Types (Pair, Parser, parseEither)
import Data.Monoid (Endo(..))
import HaskellWorks.Data.Aeson.Compat (Key)
import Text.Read (readMaybe)
import qualified Data.Aeson as J
import qualified Data.Aeson.Types as J
import qualified Data.ByteString.Lazy as LBS
infixr 7 .?=
infixr 7 .!=
newtype JsonEndo a = JsonEndo
{ forall a. JsonEndo a -> [a] -> [a]
unJsonEndo :: [a] -> [a]
}
deriving (NonEmpty (JsonEndo a) -> JsonEndo a
JsonEndo a -> JsonEndo a -> JsonEndo a
forall b. Integral b => b -> JsonEndo a -> JsonEndo a
forall a. NonEmpty (JsonEndo a) -> JsonEndo a
forall a. JsonEndo a -> JsonEndo a -> JsonEndo a
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
forall a b. Integral b => b -> JsonEndo a -> JsonEndo a
stimes :: forall b. Integral b => b -> JsonEndo a -> JsonEndo a
$cstimes :: forall a b. Integral b => b -> JsonEndo a -> JsonEndo a
sconcat :: NonEmpty (JsonEndo a) -> JsonEndo a
$csconcat :: forall a. NonEmpty (JsonEndo a) -> JsonEndo a
<> :: JsonEndo a -> JsonEndo a -> JsonEndo a
$c<> :: forall a. JsonEndo a -> JsonEndo a -> JsonEndo a
Semigroup, JsonEndo a
[JsonEndo a] -> JsonEndo a
JsonEndo a -> JsonEndo a -> JsonEndo a
forall a. Semigroup (JsonEndo a)
forall a. JsonEndo a
forall a.
Semigroup a -> a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
forall a. [JsonEndo a] -> JsonEndo a
forall a. JsonEndo a -> JsonEndo a -> JsonEndo a
mconcat :: [JsonEndo a] -> JsonEndo a
$cmconcat :: forall a. [JsonEndo a] -> JsonEndo a
mappend :: JsonEndo a -> JsonEndo a -> JsonEndo a
$cmappend :: forall a. JsonEndo a -> JsonEndo a -> JsonEndo a
mempty :: JsonEndo a
$cmempty :: forall a. JsonEndo a
Monoid) via (Endo [a])
#if MIN_VERSION_aeson(2,2,0)
instance (ToJSON e, KeyValue e a) => KeyValue e (JsonEndo a) where
explicitToField f k v = JsonEndo (k .= f v :)
#else
instance KeyValue a => KeyValue (JsonEndo a) where
#endif
Key
k .= :: forall v. ToJSON v => Key -> v -> JsonEndo a
.= v
v = forall a. ([a] -> [a]) -> JsonEndo a
JsonEndo (Key
k forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= v
v forall a. a -> [a] -> [a]
:)
objectWithoutNulls :: [Pair] -> Value
objectWithoutNulls :: [Pair] -> Value
objectWithoutNulls = [Pair] -> Value
object forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> Bool) -> [a] -> [a]
Prelude.filter (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. Value -> Bool
isNull forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> b
snd)
where
isNull :: Value -> Bool
isNull Value
Null = Bool
True
isNull Value
_ = Bool
False
readJson :: Read a => String -> String -> Parser a
readJson :: forall a. Read a => String -> String -> Parser a
readJson String
t String
s = case forall a. Read a => String -> Maybe a
readMaybe String
s of
Just a
a -> forall (f :: * -> *) a. Applicative f => a -> f a
pure a
a
Maybe a
Nothing -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail forall a b. (a -> b) -> a -> b
$ String
"Could not parse " forall a. Semigroup a => a -> a -> a
<> String
t
#if MIN_VERSION_aeson(2,2,0)
(.?=) :: (KeyValue e p, ToJSON v, Monoid p) => Key -> Maybe v -> p
#else
(.?=) :: (KeyValue p, ToJSON v, Monoid p) => Key -> Maybe v -> p
#endif
.?= :: forall p v. (KeyValue p, ToJSON v, Monoid p) => Key -> Maybe v -> p
(.?=) Key
k Maybe v
mv = case Maybe v
mv of
Just v
v -> Key
k forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= v
v
Maybe v
Nothing -> forall a. Monoid a => a
mempty
#if MIN_VERSION_aeson(2,2,0)
(.!=) :: (KeyValue e kv, ToJSON v) => Key -> v -> kv
#else
(.!=) :: (KeyValue kv, ToJSON v) => Key -> v -> kv
#endif
.!= :: forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
(.!=) = forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
(.=)
objectEndo :: [JsonEndo Pair] -> Value
objectEndo :: [JsonEndo Pair] -> Value
objectEndo [JsonEndo Pair]
es = [Pair] -> Value
object forall a b. (a -> b) -> a -> b
$ forall a. JsonEndo a -> [a] -> [a]
unJsonEndo (forall a. Monoid a => [a] -> a
mconcat [JsonEndo Pair]
es) []
class ToJsonKeyValues a where
#if MIN_VERSION_aeson(2,2,0)
toJsonKeyValues :: (KeyValue e kv, Monoid kv) => a -> [kv]
#else
toJsonKeyValues :: (KeyValue kv, Monoid kv) => a -> [kv]
#endif
newtype WithJsonKeyValues a = WithJsonKeyValues
{ forall a. WithJsonKeyValues a -> a
unWithJsonKeyValues :: a
}
instance ToJsonKeyValues a => ToJSON (WithJsonKeyValues a) where
toJSON :: WithJsonKeyValues a -> Value
toJSON = [JsonEndo Pair] -> Value
objectEndo forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a kv.
(ToJsonKeyValues a, KeyValue kv, Monoid kv) =>
a -> [kv]
toJsonKeyValues forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. WithJsonKeyValues a -> a
unWithJsonKeyValues
toEncoding :: WithJsonKeyValues a -> Encoding
toEncoding = Series -> Encoding
pairs forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Monoid a => [a] -> a
mconcat forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a kv.
(ToJsonKeyValues a, KeyValue kv, Monoid kv) =>
a -> [kv]
toJsonKeyValues forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. WithJsonKeyValues a -> a
unWithJsonKeyValues
eitherDecodeWith :: (Value -> Parser a) -> LBS.ByteString -> Either String a
eitherDecodeWith :: forall a. (Value -> Parser a) -> ByteString -> Either String a
eitherDecodeWith Value -> Parser a
f ByteString
lbs = forall a. FromJSON a => ByteString -> Either String a
J.eitherDecode ByteString
lbs forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall a b. (a -> Parser b) -> a -> Either String b
J.parseEither Value -> Parser a
f