-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Spec based JSON parsing/serialisation -- -- Low boilerplate, easy to use and very fast JSON serialisation and -- parsing without generics or TemplateHaskell @package highjson @version 0.4.0.0 module Data.HighJson data HighSpec a (ty :: SpecType) as HighSpec :: !Text -> !(Maybe Text) -> !(BodySpec ty a as) -> HighSpec a as [hs_name] :: HighSpec a as -> !Text [hs_description] :: HighSpec a as -> !(Maybe Text) [hs_bodySpec] :: HighSpec a as -> !(BodySpec ty a as) data SpecType SpecRecord :: SpecType SpecSum :: SpecType SpecEnum :: SpecType -- | The specification for a record. Contains a name, an optional -- description, the constructor and a description how to parse and -- serialize fields respecting a given json key. recSpec :: (IsDataSpec q, DContainer q ~ RecordFields) => Text -> Maybe Text -> HVectElim (DFields q) (DType q) -> q -> RecordTypeSpec (DType q) (DFields q) -- | A specification for a record type RecordTypeSpec t flds = HighSpec t SpecRecord flds -- | A required json field. The key must be present in the json. reqField :: FromJSON f => Text -> (t -> f) -> RecordField t f -- | Alias for reqField (.=) :: FromJSON f => Text -> (t -> f) -> RecordField t f -- | An optional json field. optField :: FromJSON f => Text -> (t -> Maybe f) -> RecordField t (Maybe f) -- | Alias for optField (.=?) :: FromJSON f => Text -> (t -> Maybe f) -> RecordField t (Maybe f) -- | The specification for a sum type. Contains a name, an optional -- description and a mapping from all constructor (prims) to their -- respective json fields sumSpec :: (IsDataSpec q, DContainer q ~ SumOptions) => Text -> Maybe Text -> q -> SumTypeSpec (DType q) (DFields q) -- | A specification for an arbitrary sum type type SumTypeSpec t flds = HighSpec t SpecSum flds -- | An option of a sum type sumOpt :: Text -> Prism' t o -> SumOption t o -- | Alias for sumOpt (.->) :: Text -> Prism' t o -> SumOption t o -- | The specification for a classic enum type. Contains a name, an -- optional description and a mapping from all constructors to ther -- counterpart json string names. enumSpec :: (IsDataSpec q, DContainer q ~ PhantomEnumContainer) => Text -> Maybe Text -> q -> EnumTypeSpec (DType q) (DFields q) -- | A specification for a classic enum type EnumTypeSpec t flds = HighSpec t SpecEnum flds -- | An option of a classic enum enumOpt :: Text -> Prism' t () -> EnumOption t -- | Alias for enumOpt (@->) :: Text -> Prism' t () -> EnumOption t -- | A type class that allows a unified notation for records and sum types. -- Build specifications using '(:&)' and '(.=)', '(.=?)', '(.->)' -- or '(@->)' class IsDataSpec t where type DFields t :: [*] type DType t type DContainer t :: * -> [*] -> * where { type family DFields t :: [*]; type family DType t; type family DContainer t :: * -> [*] -> *; } compileRec :: IsDataSpec t => t -> (DContainer t) (DType t) (DFields t) -- | Combination of two local specifications. For records, these are -- fields, for sum types and enums these are the options. data (:&) a b (:&) :: a -> b -> (:&) a b jsonSerializer :: AllHave ToJSON as => HighSpec a ty as -> a -> Value jsonEncoder :: AllHave ToJSON as => HighSpec a ty as -> a -> Encoding jsonParser :: AllHave FromJSON as => HighSpec a ty as -> Value -> Parser a data BodySpec ty a as [BodySpecRecord] :: !(RecordSpec a as) -> BodySpec SpecRecord a as [BodySpecSum] :: !(SumSpec a as) -> BodySpec SpecSum a as [BodySpecEnum] :: !(EnumSpec a) -> BodySpec SpecEnum a as data RecordField t f RecordField :: !Text -> !Bool -> (Object -> Text -> Parser f) -> !(t -> f) -> RecordField t f [rf_jsonKey] :: RecordField t f -> !Text [rf_optional] :: RecordField t f -> !Bool [rf_jsonLoader] :: RecordField t f -> Object -> Text -> Parser f [rf_get] :: RecordField t f -> !(t -> f) data RecordSpec a fs RecordSpec :: (HVect fs -> a) -> RecordFields a fs -> RecordSpec a fs [rs_make] :: RecordSpec a fs -> HVect fs -> a [rs_fields] :: RecordSpec a fs -> RecordFields a fs data RecordFields t fs [RFEmpty] :: RecordFields t '[] [:+:] :: RecordField t f -> RecordFields t fs -> RecordFields t (f : fs) data SumOption t o SumOption :: !Text -> !(Prism' t o) -> SumOption t o [so_jsonKey] :: SumOption t o -> !Text [so_prism] :: SumOption t o -> !(Prism' t o) data SumSpec a os SumSpec :: SumOptions a os -> SumSpec a os [ss_options] :: SumSpec a os -> SumOptions a os data SumOptions t os [SOEmpty] :: SumOptions t '[] [:|:] :: SumOption t o -> SumOptions t os -> SumOptions t (o : os) data EnumOption t EnumOption :: !Text -> !(Prism' t ()) -> EnumOption t [eo_jsonKey] :: EnumOption t -> !Text [eo_prism] :: EnumOption t -> !(Prism' t ()) data EnumSpec a EnumSpec :: [EnumOption a] -> EnumSpec a [es_options] :: EnumSpec a -> [EnumOption a] -- | A type that can be converted to JSON. -- -- An example type and instance: -- --
-- -- Allow ourselves to write Text literals.
-- {-# LANGUAGE OverloadedStrings #-}
--
-- data Coord = Coord { x :: Double, y :: Double }
--
-- instance ToJSON Coord where
-- toJSON (Coord x y) = object ["x" .= x, "y" .= y]
--
-- toEncoding (Coord x y) = pairs ("x" .= x <> "y" .= y)
--
--
-- Instead of manually writing your ToJSON instance, there are two
-- options to do it automatically:
--
--
-- {-# LANGUAGE DeriveGeneric #-}
--
-- import GHC.Generics
--
-- data Coord = Coord { x :: Double, y :: Double } deriving Generic
--
-- instance ToJSON Coord where
-- toEncoding = genericToEncoding defaultOptions
--
--
-- Why do we provide an implementation for toEncoding here? The
-- toEncoding function is a relatively new addition to this class.
-- To allow users of older versions of this library to upgrade without
-- having to edit all of their instances or encounter surprising
-- incompatibilities, the default implementation of toEncoding
-- uses toJSON. This produces correct results, but since it
-- performs an intermediate conversion to a Value, it will be less
-- efficient than directly emitting an Encoding. Our one-liner
-- definition of toEncoding above bypasses the intermediate
-- Value.
--
-- If DefaultSignatures doesn't give exactly the results you
-- want, you can customize the generic encoding with only a tiny amount
-- of effort, using genericToJSON and genericToEncoding
-- with your preferred Options:
--
-- -- instance ToJSON Coord where -- toJSON = genericToJSON defaultOptions -- toEncoding = genericToEncoding defaultOptions --class ToJSON a -- | Convert a Haskell value to a JSON-friendly intermediate type. toJSON :: ToJSON a => a -> Value -- | Encode a Haskell value as JSON. -- -- The default implementation of this method creates an intermediate -- Value using toJSON. This provides source-level -- compatibility for people upgrading from older versions of this -- library, but obviously offers no performance advantage. -- -- To benefit from direct encoding, you must provide an -- implementation for this method. The easiest way to do so is by having -- your types implement Generic using the DeriveGeneric -- extension, and then have GHC generate a method body as follows. -- --
-- instance ToJSON Coord where -- toEncoding = genericToEncoding defaultOptions --toEncoding :: ToJSON a => a -> Encoding toJSONList :: ToJSON a => [a] -> Value toEncodingList :: ToJSON a => [a] -> Encoding -- | A type that can be converted from JSON, with the possibility of -- failure. -- -- In many cases, you can get the compiler to generate parsing code for -- you (see below). To begin, let's cover writing an instance by hand. -- -- There are various reasons a conversion could fail. For example, an -- Object could be missing a required key, an Array could -- be of the wrong size, or a value could be of an incompatible type. -- -- The basic ways to signal a failed conversion are as follows: -- --
-- -- Allow ourselves to write Text literals.
-- {-# LANGUAGE OverloadedStrings #-}
--
-- data Coord = Coord { x :: Double, y :: Double }
--
-- instance FromJSON Coord where
-- parseJSON (Object v) = Coord <$>
-- v .: "x" <*>
-- v .: "y"
--
-- -- We do not expect a non-Object value here.
-- -- We could use mzero to fail, but typeMismatch
-- -- gives a much more informative error message.
-- parseJSON invalid = typeMismatch "Coord" invalid
--
--
-- Instead of manually writing your FromJSON instance, there are
-- two options to do it automatically:
--
--
-- {-# LANGUAGE DeriveGeneric #-}
--
-- import GHC.Generics
--
-- data Coord = Coord { x :: Double, y :: Double } deriving Generic
--
-- instance FromJSON Coord
--
--
-- If DefaultSignatures doesn't give exactly the results you
-- want, you can customize the generic decoding with only a tiny amount
-- of effort, using genericParseJSON with your preferred
-- Options:
--
-- -- instance FromJSON Coord where -- parseJSON = genericParseJSON defaultOptions --class FromJSON a parseJSON :: FromJSON a => Value -> Parser a parseJSONList :: FromJSON a => Value -> Parser [a] newtype PhantomEnumContainer t (ts :: [*]) PhantomEnumContainer :: [EnumOption t] -> PhantomEnumContainer t [unPhantomEnumContainer] :: PhantomEnumContainer t -> [EnumOption t] -- | A monoidal type class that respects type level lists associated to the -- bodies class CombinableContainer t combineContainer :: CombinableContainer t => t a (as :: [*]) -> t a (bs :: [*]) -> t a (Append as bs) instance (GHC.Enum.Bounded b, GHC.Enum.Bounded a) => GHC.Enum.Bounded (a Data.HighJson.:& b) instance Data.Foldable.Foldable ((Data.HighJson.:&) a) instance Data.Traversable.Traversable ((Data.HighJson.:&) a) instance GHC.Base.Functor ((Data.HighJson.:&) a) instance (GHC.Show.Show b, GHC.Show.Show a) => GHC.Show.Show (a Data.HighJson.:& b) instance (GHC.Classes.Eq b, GHC.Classes.Eq a) => GHC.Classes.Eq (a Data.HighJson.:& b) instance (GHC.Base.Monoid a, GHC.Base.Monoid b) => GHC.Base.Monoid (a Data.HighJson.:& b) instance Data.HighJson.CombinableContainer Data.HighJson.Types.RecordFields instance Data.HighJson.CombinableContainer Data.HighJson.Types.SumOptions instance Data.HighJson.CombinableContainer Data.HighJson.PhantomEnumContainer instance Data.HighJson.IsDataSpec (Data.HighJson.Types.RecordField t f) instance Data.HighJson.IsDataSpec (Data.HighJson.Types.SumOption t f) instance Data.HighJson.IsDataSpec (Data.HighJson.Types.EnumOption t) instance (Data.HighJson.IsDataSpec x, Data.HighJson.IsDataSpec y, Data.HighJson.DType x ~ Data.HighJson.DType y, Data.HighJson.DContainer x ~ Data.HighJson.DContainer y, Data.HighJson.CombinableContainer (Data.HighJson.DContainer x)) => Data.HighJson.IsDataSpec (x Data.HighJson.:& y)