-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Better error messages when decoding JSON values. -- @package aeson-better-errors @version 0.9.0 module Data.Aeson.BetterErrors.Internal -- | The type of parsers: things which consume JSON values and produce -- either detailed errors or successfully parsed values (of other types). -- -- The err type parameter is for custom validation errors; for -- parsers that don't produce any custom validation errors, I recommend -- you just stick a type variable in for full generality: -- --
--   asTuple :: Parse e (Int, Int)
--   asTuple = (,) <$> nth 0 asIntegral <*> nth 1 asIntegral
--   
-- -- The m parameter allows you to run the parser within an -- abitrary underlying Monad. You may want to use Parse in most -- cases instead, and all functions in this module work on either. newtype ParseT err m a ParseT :: (ReaderT ParseReader (ExceptT (ParseError err) m) a) -> ParseT err m a -- | This is the standard version of ParseT over the Identity -- Monad, for running pure parsers. type Parse err a = ParseT err Identity a runParseT :: ParseT err m a -> Value -> m (Either (ParseError err) a) runParse :: Parse err a -> Value -> Either (ParseError err) a mapParseT :: (ReaderT ParseReader (ExceptT (ParseError err) m) a -> ReaderT ParseReader (ExceptT (ParseError err') m') a') -> ParseT err m a -> ParseT err' m' a' -- | Transform the error of a parser according to the given function. mapError :: Functor m => (err -> err') -> ParseT err m a -> ParseT err' m a -- | An infix version of mapError. (.!) :: Functor m => ParseT err m a -> (err -> err') -> ParseT err' m a -- | The type of parsers which never produce custom validation errors. type Parse' a = Parse Void a runParserT :: Monad m => (s -> Either String Value) -> ParseT err m a -> s -> m (Either (ParseError err) a) runParser :: (s -> Either String Value) -> Parse err a -> s -> Either (ParseError err) a -- | Like parse but runs the parser on an arbitrary underlying -- Monad. parseM :: Monad m => ParseT err m a -> ByteString -> m (Either (ParseError err) a) -- | Run a parser with a lazy ByteString containing JSON data. Note -- that the normal caveat applies: the JSON supplied must contain either -- an object or an array for this to work. parse :: Parse err a -> ByteString -> Either (ParseError err) a -- | Like parseStrict but runs the parser on an arbitrary underlying -- Monad. parseStrictM :: Monad m => ParseT err m a -> ByteString -> m (Either (ParseError err) a) -- | Run a parser with a strict ByteString containing JSON data. -- Note that the normal caveat applies: the JSON supplied must contain -- either an object or an array for this to work. parseStrict :: Parse err a -> ByteString -> Either (ParseError err) a -- | Like parseValue but runs the parser on an arbitrary underlying -- Monad. parseValueM :: Monad m => ParseT err m a -> Value -> m (Either (ParseError err) a) -- | Run a parser with a pre-parsed JSON Value. parseValue :: Parse err a -> Value -> Either (ParseError err) a -- | This function is useful when you have a Parse err a -- and you want to obtain an instance for FromJSON a. -- Simply define: -- --
--   parseJSON = toAesonParser showMyCustomError myParser
--   
toAesonParser :: (err -> Text) -> Parse err a -> Value -> Parser a -- | Take a parser which never produces custom validation errors and turn -- it into an Aeson parser. Note that in this case, there is no need to -- provide a display function. toAesonParser' :: Parse' a -> Value -> Parser a -- | Create a parser for any type, using its FromJSON instance. Generally, -- you should prefer to write parsers using the other functions in this -- module; key, asString, etc, since they will usually -- generate better error messages. However this function is also useful -- occasionally. fromAesonParser :: (Functor m, Monad m) => FromJSON a => ParseT e m a -- | Data used internally by the Parse type. data ParseReader ParseReader :: DList PathPiece -> Value -> ParseReader rdrPath :: ParseReader -> DList PathPiece rdrValue :: ParseReader -> Value appendPath :: PathPiece -> ParseReader -> ParseReader setValue :: Value -> ParseReader -> ParseReader -- | A piece of a path leading to a specific part of the JSON data. -- Internally, a list of these is maintained as the parser traverses the -- JSON data. This list is included in the error if one occurs. data PathPiece ObjectKey :: Text -> PathPiece ArrayIndex :: Int -> PathPiece -- | A value indicating that the JSON could not be decoded successfully. data ParseError err -- | Indicates a syntax error in the JSON string. Unfortunately, in this -- case, Aeson's errors are not very helpful. InvalidJSON :: String -> ParseError err -- | Indicates a decoding error; the input was parsed as JSON successfully, -- but a value of the required type could not be constructed, perhaps -- because of a missing key or type mismatch. BadSchema :: [PathPiece] -> (ErrorSpecifics err) -> ParseError err -- | The type of parse errors which never involve custom validation errors. type ParseError' = ParseError Void -- | Detailed information in the case where a value could be parsed as -- JSON, but a value of the required type could not be constructed from -- it, for some reason. data ErrorSpecifics err KeyMissing :: Text -> ErrorSpecifics err OutOfBounds :: Int -> ErrorSpecifics err -- | Expected type, actual value WrongType :: JSONType -> Value -> ErrorSpecifics err ExpectedIntegral :: Double -> ErrorSpecifics err -- | An error arising inside a FromJSON instance. FromAeson :: String -> ErrorSpecifics err CustomError :: err -> ErrorSpecifics err -- | The type of error specifics which never involve custom validation -- errors. type ErrorSpecifics' = ErrorSpecifics Void -- | An enumeration of the different types that JSON values may take. data JSONType TyObject :: JSONType TyArray :: JSONType TyString :: JSONType TyNumber :: JSONType TyBool :: JSONType TyNull :: JSONType displayJSONType :: JSONType -> Text -- | Turn a ParseError into a human-readable list of Text -- values. They will be in a sensible order. For example, you can feed -- the result to mapM putStrLn, or unlines. displayError :: (err -> Text) -> ParseError err -> [Text] -- | A version of displayError for parsers which do not produce -- custom validation errors. displayError' :: ParseError' -> [Text] displayPath :: [PathPiece] -> Text displaySpecifics :: (err -> Text) -> ErrorSpecifics err -> [Text] -- | A version of displaySpecifics for parsers which do not produce -- custom validation errors. displaySpecifics' :: ErrorSpecifics' -> [Text] -- | Get the type of a JSON value. jsonTypeOf :: Value -> JSONType liftParseT :: (Functor m, Monad m) => (Value -> ExceptT (ErrorSpecifics err) m a) -> ParseT err m a liftParseM :: (Functor m, Monad m) => (Value -> m (Either (ErrorSpecifics err) a)) -> ParseT err m a -- | Lift any parsing function into the Parse type. liftParse :: (Functor m, Monad m) => (Value -> Either (ErrorSpecifics err) a) -> ParseT err m a -- | Aborts parsing, due to an error in the structure of the JSON - that -- is, any error other than the JSON not actually being parseable into a -- Value. badSchema :: (Functor m, Monad m) => ErrorSpecifics err -> ParseT err m a as :: (Functor m, Monad m) => (Value -> Maybe a) -> JSONType -> ParseT err m a -- | Parse a single JSON string as Text. asText :: (Functor m, Monad m) => ParseT err m Text -- | Parse a single JSON string as a String. asString :: (Functor m, Monad m) => ParseT err m String -- | Parse a single JSON number as a Scientific. asScientific :: (Functor m, Monad m) => ParseT err m Scientific -- | Parse a single JSON number as any Integral type. asIntegral :: (Functor m, Monad m, Integral a) => ParseT err m a -- | Parse a single JSON number as any RealFloat type. asRealFloat :: (Functor m, Monad m, RealFloat a) => ParseT err m a -- | Parse a single JSON boolean as a Bool. asBool :: (Functor m, Monad m) => ParseT err m Bool -- | Parse a JSON object, as an Object. You should prefer functions -- like eachInObject where possible, since they will usually -- generate better error messages. asObject :: (Functor m, Monad m) => ParseT err m Object -- | Parse a JSON array, as an Array. You should prefer functions -- like eachInArray where possible, since they will usually -- generate better error messages. asArray :: (Functor m, Monad m) => ParseT err m Array -- | Parse a single JSON null value. Useful if you want to throw an error -- in the case where something is not null. asNull :: (Functor m, Monad m) => ParseT err m () -- | Given a parser, transform it into a parser which returns -- Nothing when supplied with a JSON null, and -- otherwise, attempts to parse with the original parser; if this -- succeeds, the result becomes a Just value. perhaps :: (Functor m, Monad m) => ParseT err m a -> ParseT err m (Maybe a) -- | Take the value corresponding to a given key in the current object. key :: (Functor m, Monad m) => Text -> ParseT err m a -> ParseT err m a -- | Take the value corresponding to a given key in the current object, or -- if no property exists with that key, use the supplied default. keyOrDefault :: (Functor m, Monad m) => Text -> a -> ParseT err m a -> ParseT err m a -- | Take the value corresponding to a given key in the current object, or -- if no property exists with that key, return Nothing . keyMay :: (Functor m, Monad m) => Text -> ParseT err m a -> ParseT err m (Maybe a) key' :: (Functor m, Monad m) => ParseT err m a -> Text -> ParseT err m a -> ParseT err m a -- | Take the nth value of the current array. nth :: (Functor m, Monad m) => Int -> ParseT err m a -> ParseT err m a -- | Take the nth value of the current array, or if no value exists with -- that index, use the supplied default. nthOrDefault :: (Functor m, Monad m) => Int -> a -> ParseT err m a -> ParseT err m a -- | Take the nth value of the current array, or if no value exists with -- that index, return Nothing. nthMay :: (Functor m, Monad m) => Int -> ParseT err m a -> ParseT err m (Maybe a) nth' :: (Functor m, Monad m) => ParseT err m a -> Int -> ParseT err m a -> ParseT err m a -- | Attempt to parse each value in the array with the given parser, and -- collect the results. eachInArray :: (Functor m, Monad m) => ParseT err m a -> ParseT err m [a] -- | Attempt to parse each property value in the object with the given -- parser, and collect the results. eachInObject :: (Functor m, Monad m) => ParseT err m a -> ParseT err m [(Text, a)] -- | Attempt to parse each property in the object: parse the key with the -- given validation function, parse the value with the given parser, and -- collect the results. eachInObjectWithKey :: (Functor m, Monad m) => (Text -> Either err k) -> ParseT err m a -> ParseT err m [(k, a)] -- | Lifts a function attempting to validate an arbitrary JSON value into a -- parser. You should only use this if absolutely necessary; the other -- functions in this module will generally give better error reporting. withValue :: (Functor m, Monad m) => (Value -> Either err a) -> ParseT err m a liftEither :: (Functor m, Monad m) => Either err a -> ParseT err m a withM :: (Functor m, Monad m) => ParseT err m a -> (a -> m (Either err b)) -> ParseT err m b with :: (Functor m, Monad m) => ParseT err m a -> (a -> Either err b) -> ParseT err m b withTextM :: (Functor m, Monad m) => (Text -> m (Either err a)) -> ParseT err m a withText :: (Functor m, Monad m) => (Text -> Either err a) -> ParseT err m a withStringM :: (Functor m, Monad m) => (String -> m (Either err a)) -> ParseT err m a withString :: (Functor m, Monad m) => (String -> Either err a) -> ParseT err m a withScientificM :: (Functor m, Monad m) => (Scientific -> m (Either err a)) -> ParseT err m a withScientific :: (Functor m, Monad m) => (Scientific -> Either err a) -> ParseT err m a withIntegralM :: (Functor m, Monad m, Integral a) => (a -> m (Either err b)) -> ParseT err m b withIntegral :: (Functor m, Monad m, Integral a) => (a -> Either err b) -> ParseT err m b withRealFloatM :: (Functor m, Monad m, RealFloat a) => (a -> m (Either err b)) -> ParseT err m b withRealFloat :: (Functor m, Monad m, RealFloat a) => (a -> Either err b) -> ParseT err m b withBoolM :: (Functor m, Monad m) => (Bool -> m (Either err a)) -> ParseT err m a withBool :: (Functor m, Monad m) => (Bool -> Either err a) -> ParseT err m a -- | Prefer to use functions like key or eachInObject to this -- one where possible, as they will generate better error messages. withObjectM :: (Functor m, Monad m) => (Object -> m (Either err a)) -> ParseT err m a -- | Prefer to use functions like key or eachInObject to this -- one where possible, as they will generate better error messages. withObject :: (Functor m, Monad m) => (Object -> Either err a) -> ParseT err m a -- | Prefer to use functions like nth or eachInArray to this -- one where possible, as they will generate better error messages. withArrayM :: (Functor m, Monad m) => (Array -> m (Either err a)) -> ParseT err m a -- | Prefer to use functions like nth or eachInArray to this -- one where possible, as they will generate better error messages. withArray :: (Functor m, Monad m) => (Array -> Either err a) -> ParseT err m a -- | Throw a custom validation error. throwCustomError :: (Functor m, Monad m) => err -> ParseT err m a liftCustomT :: (Functor m, Monad m) => ExceptT err m a -> ParseT err m a instance Show PathPiece instance Eq PathPiece instance Ord PathPiece instance Show JSONType instance Eq JSONType instance Ord JSONType instance Show err => Show (ErrorSpecifics err) instance Eq err => Eq (ErrorSpecifics err) instance Functor ErrorSpecifics instance Show err => Show (ParseError err) instance Eq err => Eq (ParseError err) instance Functor ParseError instance Functor m => Functor (ParseT err m) instance (Monad m, Functor m) => Applicative (ParseT err m) instance Monad m => Monad (ParseT err m) instance Monad m => MonadReader ParseReader (ParseT err m) instance Monad m => MonadError (ParseError err) (ParseT err m) instance MonadTrans (ParseT err) -- | A module for decoding JSON, and generating good error messages. Note, -- however, that this package only deals with generating good error -- messages after the JSON has been parsed into a Value - -- unfortunately, invalid JSON will still produce poor error messages. -- -- See http://harry.garrood.me/blog/aeson-better-errors/ for a -- tutorial. -- -- Any kind of feedback is very welcome: suggestions for a better -- designed API, bug reports, whatever - the best place for it is -- probably the GitHub issue tracker: -- https://github.com/hdgarrood/aeson-better-errors/issues. module Data.Aeson.BetterErrors -- | The type of parsers: things which consume JSON values and produce -- either detailed errors or successfully parsed values (of other types). -- -- The err type parameter is for custom validation errors; for -- parsers that don't produce any custom validation errors, I recommend -- you just stick a type variable in for full generality: -- --
--   asTuple :: Parse e (Int, Int)
--   asTuple = (,) <$> nth 0 asIntegral <*> nth 1 asIntegral
--   
-- -- The m parameter allows you to run the parser within an -- abitrary underlying Monad. You may want to use Parse in most -- cases instead, and all functions in this module work on either. data ParseT err m a -- | This is the standard version of ParseT over the Identity -- Monad, for running pure parsers. type Parse err a = ParseT err Identity a -- | The type of parsers which never produce custom validation errors. type Parse' a = Parse Void a -- | Transform the error of a parser according to the given function. mapError :: Functor m => (err -> err') -> ParseT err m a -> ParseT err' m a -- | An infix version of mapError. (.!) :: Functor m => ParseT err m a -> (err -> err') -> ParseT err' m a -- | Parse a single JSON string as Text. asText :: (Functor m, Monad m) => ParseT err m Text -- | Parse a single JSON string as a String. asString :: (Functor m, Monad m) => ParseT err m String -- | Parse a single JSON number as a Scientific. asScientific :: (Functor m, Monad m) => ParseT err m Scientific -- | Parse a single JSON number as any Integral type. asIntegral :: (Functor m, Monad m, Integral a) => ParseT err m a -- | Parse a single JSON number as any RealFloat type. asRealFloat :: (Functor m, Monad m, RealFloat a) => ParseT err m a -- | Parse a single JSON boolean as a Bool. asBool :: (Functor m, Monad m) => ParseT err m Bool -- | Parse a single JSON null value. Useful if you want to throw an error -- in the case where something is not null. asNull :: (Functor m, Monad m) => ParseT err m () -- | Parse a JSON object, as an Object. You should prefer functions -- like eachInObject where possible, since they will usually -- generate better error messages. asObject :: (Functor m, Monad m) => ParseT err m Object -- | Parse a JSON array, as an Array. You should prefer functions -- like eachInArray where possible, since they will usually -- generate better error messages. asArray :: (Functor m, Monad m) => ParseT err m Array -- | Given a parser, transform it into a parser which returns -- Nothing when supplied with a JSON null, and -- otherwise, attempts to parse with the original parser; if this -- succeeds, the result becomes a Just value. perhaps :: (Functor m, Monad m) => ParseT err m a -> ParseT err m (Maybe a) -- | Take the value corresponding to a given key in the current object. key :: (Functor m, Monad m) => Text -> ParseT err m a -> ParseT err m a -- | Take the value corresponding to a given key in the current object, or -- if no property exists with that key, use the supplied default. keyOrDefault :: (Functor m, Monad m) => Text -> a -> ParseT err m a -> ParseT err m a -- | Take the value corresponding to a given key in the current object, or -- if no property exists with that key, return Nothing . keyMay :: (Functor m, Monad m) => Text -> ParseT err m a -> ParseT err m (Maybe a) -- | Take the nth value of the current array. nth :: (Functor m, Monad m) => Int -> ParseT err m a -> ParseT err m a -- | Take the nth value of the current array, or if no value exists with -- that index, use the supplied default. nthOrDefault :: (Functor m, Monad m) => Int -> a -> ParseT err m a -> ParseT err m a -- | Take the nth value of the current array, or if no value exists with -- that index, return Nothing. nthMay :: (Functor m, Monad m) => Int -> ParseT err m a -> ParseT err m (Maybe a) -- | Attempt to parse each value in the array with the given parser, and -- collect the results. eachInArray :: (Functor m, Monad m) => ParseT err m a -> ParseT err m [a] -- | Attempt to parse each property value in the object with the given -- parser, and collect the results. eachInObject :: (Functor m, Monad m) => ParseT err m a -> ParseT err m [(Text, a)] -- | Attempt to parse each property in the object: parse the key with the -- given validation function, parse the value with the given parser, and -- collect the results. eachInObjectWithKey :: (Functor m, Monad m) => (Text -> Either err k) -> ParseT err m a -> ParseT err m [(k, a)] withText :: (Functor m, Monad m) => (Text -> Either err a) -> ParseT err m a withString :: (Functor m, Monad m) => (String -> Either err a) -> ParseT err m a withScientific :: (Functor m, Monad m) => (Scientific -> Either err a) -> ParseT err m a withIntegral :: (Functor m, Monad m, Integral a) => (a -> Either err b) -> ParseT err m b withRealFloat :: (Functor m, Monad m, RealFloat a) => (a -> Either err b) -> ParseT err m b withBool :: (Functor m, Monad m) => (Bool -> Either err a) -> ParseT err m a -- | Prefer to use functions like key or eachInObject to this -- one where possible, as they will generate better error messages. withObject :: (Functor m, Monad m) => (Object -> Either err a) -> ParseT err m a -- | Prefer to use functions like nth or eachInArray to this -- one where possible, as they will generate better error messages. withArray :: (Functor m, Monad m) => (Array -> Either err a) -> ParseT err m a -- | Throw a custom validation error. throwCustomError :: (Functor m, Monad m) => err -> ParseT err m a withTextM :: (Functor m, Monad m) => (Text -> m (Either err a)) -> ParseT err m a withStringM :: (Functor m, Monad m) => (String -> m (Either err a)) -> ParseT err m a withScientificM :: (Functor m, Monad m) => (Scientific -> m (Either err a)) -> ParseT err m a withIntegralM :: (Functor m, Monad m, Integral a) => (a -> m (Either err b)) -> ParseT err m b withRealFloatM :: (Functor m, Monad m, RealFloat a) => (a -> m (Either err b)) -> ParseT err m b withBoolM :: (Functor m, Monad m) => (Bool -> m (Either err a)) -> ParseT err m a -- | Prefer to use functions like key or eachInObject to this -- one where possible, as they will generate better error messages. withObjectM :: (Functor m, Monad m) => (Object -> m (Either err a)) -> ParseT err m a -- | Prefer to use functions like nth or eachInArray to this -- one where possible, as they will generate better error messages. withArrayM :: (Functor m, Monad m) => (Array -> m (Either err a)) -> ParseT err m a -- | Run a parser with a lazy ByteString containing JSON data. Note -- that the normal caveat applies: the JSON supplied must contain either -- an object or an array for this to work. parse :: Parse err a -> ByteString -> Either (ParseError err) a -- | Run a parser with a strict ByteString containing JSON data. -- Note that the normal caveat applies: the JSON supplied must contain -- either an object or an array for this to work. parseStrict :: Parse err a -> ByteString -> Either (ParseError err) a -- | Run a parser with a pre-parsed JSON Value. parseValue :: Parse err a -> Value -> Either (ParseError err) a -- | Like parse but runs the parser on an arbitrary underlying -- Monad. parseM :: Monad m => ParseT err m a -> ByteString -> m (Either (ParseError err) a) -- | Like parseStrict but runs the parser on an arbitrary underlying -- Monad. parseStrictM :: Monad m => ParseT err m a -> ByteString -> m (Either (ParseError err) a) -- | Like parseValue but runs the parser on an arbitrary underlying -- Monad. parseValueM :: Monad m => ParseT err m a -> Value -> m (Either (ParseError err) a) -- | A value indicating that the JSON could not be decoded successfully. data ParseError err -- | Indicates a syntax error in the JSON string. Unfortunately, in this -- case, Aeson's errors are not very helpful. InvalidJSON :: String -> ParseError err -- | Indicates a decoding error; the input was parsed as JSON successfully, -- but a value of the required type could not be constructed, perhaps -- because of a missing key or type mismatch. BadSchema :: [PathPiece] -> (ErrorSpecifics err) -> ParseError err -- | The type of parse errors which never involve custom validation errors. type ParseError' = ParseError Void -- | A piece of a path leading to a specific part of the JSON data. -- Internally, a list of these is maintained as the parser traverses the -- JSON data. This list is included in the error if one occurs. data PathPiece ObjectKey :: Text -> PathPiece ArrayIndex :: Int -> PathPiece -- | Detailed information in the case where a value could be parsed as -- JSON, but a value of the required type could not be constructed from -- it, for some reason. data ErrorSpecifics err KeyMissing :: Text -> ErrorSpecifics err OutOfBounds :: Int -> ErrorSpecifics err -- | Expected type, actual value WrongType :: JSONType -> Value -> ErrorSpecifics err ExpectedIntegral :: Double -> ErrorSpecifics err -- | An error arising inside a FromJSON instance. FromAeson :: String -> ErrorSpecifics err CustomError :: err -> ErrorSpecifics err -- | The type of error specifics which never involve custom validation -- errors. type ErrorSpecifics' = ErrorSpecifics Void -- | Turn a ParseError into a human-readable list of Text -- values. They will be in a sensible order. For example, you can feed -- the result to mapM putStrLn, or unlines. displayError :: (err -> Text) -> ParseError err -> [Text] -- | A version of displayError for parsers which do not produce -- custom validation errors. displayError' :: ParseError' -> [Text] displayPath :: [PathPiece] -> Text displaySpecifics :: (err -> Text) -> ErrorSpecifics err -> [Text] -- | A version of displaySpecifics for parsers which do not produce -- custom validation errors. displaySpecifics' :: ErrorSpecifics' -> [Text] -- | This function is useful when you have a Parse err a -- and you want to obtain an instance for FromJSON a. -- Simply define: -- --
--   parseJSON = toAesonParser showMyCustomError myParser
--   
toAesonParser :: (err -> Text) -> Parse err a -> Value -> Parser a -- | Take a parser which never produces custom validation errors and turn -- it into an Aeson parser. Note that in this case, there is no need to -- provide a display function. toAesonParser' :: Parse' a -> Value -> Parser a -- | Create a parser for any type, using its FromJSON instance. Generally, -- you should prefer to write parsers using the other functions in this -- module; key, asString, etc, since they will usually -- generate better error messages. However this function is also useful -- occasionally. fromAesonParser :: (Functor m, Monad m) => FromJSON a => ParseT e m a -- | An enumeration of the different types that JSON values may take. data JSONType TyObject :: JSONType TyArray :: JSONType TyString :: JSONType TyNumber :: JSONType TyBool :: JSONType TyNull :: JSONType -- | Get the type of a JSON value. jsonTypeOf :: Value -> JSONType