uniform-json-0.1.5.2: src/Uniform/Json.hs
----------------------------------------------------------------------
--
-- Module : Uniform.Json
--
------------------------------------------------- --------------------
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DoAndIfThenElse #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
-- | the operations on JSON data types
module Uniform.Json
( module Uniform.Json,
-- module Uniform.Error, -- or at least
ErrIO,
Value (..),
ToJSON (..),
FromJSON (..),
fromJSON,
decode,
omitNothingFields,
eitherDecode,
-- , encode
object,
(.=),
genericParseJSON,
defaultOptions,
genericToJSON,
fieldLabelModifier,
HML.fromList,
HML.toList,
Result (..),
encode,
encodePretty,
parseEither, parseMaybe
)
where
import Control.Lens
( at,
(&),
(?~),
(^?),
)
import Data.Aeson
import Data.Aeson.Types
import Data.Aeson as Aeson
-- import Data.Aeson.Lens (key, AsValue)
-- import Data.Aeson.Text
import Data.Aeson.Encode.Pretty (encodePretty)
import Data.Aeson.Lens
import qualified Data.HashMap.Lazy as HML
import qualified Data.Aeson.KeyMap as KM -- added for ghc 9.2
import UniformBase
-- import Uniform.Error hiding (at)
-- import Uniform.Strings hiding (at)
encodeT :: ToJSON a => a -> Text
encodeT = bb2t . bl2b . encode
fromJSONmaybe :: FromJSON a => Value -> Maybe a
fromJSONmaybe v = case (fromJSON v) of
Success a -> Just a
_ -> Nothing
instance Zeros Value where zero = Null
fromJSONm :: (FromJSON a, Show a) => Value -> ErrIO a
-- DO NOT USE ! fromJSONm :: (FromJSON a, MonadError m) => Value -> m a
fromJSONm v = result1 (fromJSON v)
-- fromJSONm :: (FromJSON a, MonadError m) => Value -> m a
-- | the following gives error msg
fromJSONerrio :: (FromJSON a, Show a) => Value -> ErrIO a
fromJSONerrio v = callIO $ do
result1 (fromJSON v)
fromJSONfailError :: (FromJSON a, Show a) => Value -> ErrIO a
-- | converts fromJson to a record structure
-- throws error if fails
fromJSONfailError v = case (fromJSON v) of
Success a -> return a
x -> throwErrorWords ["fromJson", showT x]
result1 :: (Monad m, MonadFail m) => Result a -> m a
result1 (Aeson.Error msg) = fail msg
result1 (Aeson.Success a) = return a
-- a difernt solution
-- | get a maybe value from a json value
gak :: Data.Aeson.Lens.AsValue s => s -> Key -> Maybe Value
gak b k = (^?) b (key k)
-- | get and set at a key
class AtKey vk v where
getAtKey :: vk -> Key -> Maybe v
getAt2Key :: vk -> Key -> Key -> Maybe v
-- ^ two keys: one after the other
putAtKey :: Key -> v -> vk -> vk
instance AtKey Value Text where
getAtKey meta2 k2 = meta2 ^? key k2 . _String
getAt2Key meta2 k1 k2 = meta2 ^? key k1 . key k2 . _String
putAtKey k2 txt meta2 = meta2 & _Object . at k2 ?~ String txt
-- instance AtKey Value [Text] where
-- getAtKey meta2 k2 = lookup k2 meta2
-- -- getAt2Key meta2 k1 k2 = meta2 ^? key k1 . key k2 . _String
-- -- putAtKey k2 txt meta2 = meta2 & _Object . at k2 ?~ String txt
instance AtKey Value Integer where
getAtKey meta2 k2 = meta2 ^? key k2 . _Integral
getAt2Key meta2 k1 k2 = meta2 ^? key k1 . key k2 . _Integral
putAtKey k2 txt meta2 = meta2 & _Object . at k2 ?~ toJSON txt
instance AtKey Value Bool where
getAtKey meta2 k2 = meta2 ^? key k2 . _Bool
getAt2Key meta2 k1 k2 = meta2 ^? key k1 . key k2 . _Bool
putAtKey k2 txt meta2 = meta2 & _Object . at k2 ?~ Bool txt
instance AtKey Value Value where
getAtKey meta2 k2 = meta2 ^? key k2
getAt2Key meta2 k1 k2 = meta2 ^? key k1 . key k2
-- putAtKey k2 txt meta2 = meta2 & _Object . at k2 ?~ Bool txt
class AtKey2 vk v where
-- getAtKey :: vk -> Key -> Maybe v
-- getAt2Key :: vk -> Key -> Text -> Maybe v
-- ^ two keys: one after the other
putAtKey2 :: Key -> v -> vk -> vk
instance (ToJSON a) => AtKey2 Value a where
-- getAtKey meta2 k2 = meta2 ^? key k2 . _Integral
-- getAt2Key meta2 k1 k2 = meta2 ^? key k1 . key k2 . _Integral
putAtKey2 k2 txt meta2 = meta2 & _Object . at k2 ?~ toJSON txt
mergeLeftPref ::[Value] -> Value
-- ^ The (left-biased) union of two maps.
-- all values must be objects, which can be prooduced with toJSON
-- It prefers the first map when duplicate keys are encountered,
-- http://hackage.haskell.org/package/hashmap-1.3.3/docs/Data-HashMap.html
-- mergeLeftPref = Object . HML.unions . map unObject
-- for ghc 9.2.1
mergeLeftPref = Object .unions' . map unObject
unions' :: [KM.KeyMap Value] -> KM.KeyMap Value
unions' = KM.fromHashMap . HML.unions . map KM.toHashMap
-- end
mergeRightPref :: [Value] -> Value
mergeRightPref = mergeLeftPref . reverse
instance NiceStrings Value where
shownice = bb2t . bl2b . encodePretty
unObject :: Value -> Object
unObject (Object x) = x
unObject z = errorT ["unObject in Json.hs: No Object available", "given", showT z]