on master help sign in
Data/Aeson.hs+2−2
since splitsnapshots
unifiedsplit
@@ -257,7 +257,7 @@ eitherDecodeStrict =
257-- | Like 'decodeFileStrict' but returns an error message when decoding fails.
257-- | Like 'decodeFileStrict' but returns an error message when decoding fails.
258eitherDecodeFileStrict :: (FromJSON a) => FilePath -> IO (Either String a)
258eitherDecodeFileStrict :: (FromJSON a) => FilePath -> IO (Either String a)
259eitherDecodeFileStrict =
259eitherDecodeFileStrict =
260− fmap eitherDecodeStrict . B.readFile
260+ fmap (eitherFormatError . eitherDecodeStrictWith jsonEOF ifromJSON) . B.readFile
261{-# INLINE eitherDecodeFileStrict #-}
261{-# INLINE eitherDecodeFileStrict #-}
262
262
263-- | Like 'decode'' but returns an error message when decoding fails.
263-- | Like 'decode'' but returns an error message when decoding fails.
@@ -274,7 +274,7 @@ eitherDecodeStrict' =
274-- | Like 'decodeFileStrict'' but returns an error message when decoding fails.
274-- | Like 'decodeFileStrict'' but returns an error message when decoding fails.
275eitherDecodeFileStrict' :: (FromJSON a) => FilePath -> IO (Either String a)
275eitherDecodeFileStrict' :: (FromJSON a) => FilePath -> IO (Either String a)
276eitherDecodeFileStrict' =
276eitherDecodeFileStrict' =
277− fmap eitherDecodeStrict' . B.readFile
277+ fmap (eitherFormatError . eitherDecodeStrictWith jsonEOF' ifromJSON) . B.readFile
278{-# INLINE eitherDecodeFileStrict' #-}
278{-# INLINE eitherDecodeFileStrict' #-}
279
279
280-- $use
280-- $use
Data/Aeson/Parser/Internal.hs+5−30
@@ -59,7 +59,6 @@ import Data.Attoparsec.ByteString.Char8 (Parser, char, decimal, endOfInput, isDi
59import Data.Function (fix)
59import Data.Function (fix)
60import Data.Functor.Compat (($>))
60import Data.Functor.Compat (($>))
61import Data.Scientific (Scientific)
61import Data.Scientific (Scientific)
62−import Data.Semigroup ((<>))
63import Data.Text (Text)
62import Data.Text (Text)
64import Data.Vector (Vector)
63import Data.Vector (Vector)
65import qualified Data.Vector as Vector (empty, fromList, fromListN, reverse)
64import qualified Data.Vector as Vector (empty, fromList, fromListN, reverse)
@@ -68,9 +67,6 @@ import qualified Data.Attoparsec.Lazy as L
68import qualified Data.ByteString as B
67import qualified Data.ByteString as B
69import qualified Data.ByteString.Unsafe as B
68import qualified Data.ByteString.Unsafe as B
70import qualified Data.ByteString.Lazy as L
69import qualified Data.ByteString.Lazy as L
71−import qualified Data.ByteString.Lazy as BSL
72−import qualified Data.ByteString.Lazy.Char8 as C
73−import qualified Data.ByteString.Builder as B
74import qualified Data.HashMap.Strict as H
70import qualified Data.HashMap.Strict as H
75import qualified Data.Scientific as Sci
71import qualified Data.Scientific as Sci
76import Data.Aeson.Parser.Unescape (unescapeText)
72import Data.Aeson.Parser.Unescape (unescapeText)
@@ -394,35 +390,14 @@ eitherDecodeWith p to s =
394 L.Done _ v -> case to v of
390 L.Done _ v -> case to v of
395 ISuccess a -> Right a
391 ISuccess a -> Right a
396 IError path msg -> Left (path, msg)
392 IError path msg -> Left (path, msg)
397− L.Fail notparsed ctx msg -> Left ([], buildMsg notparsed ctx msg)
393+ L.Fail _ ctx msg -> Left ([], buildMsg ctx msg)
398 where
394 where
399− buildMsg :: L.ByteString -> [String] -> String -> String
395+ buildMsg :: [String] -> String -> String
400− buildMsg notYetParsed [] msg = msg ++ formatErrorLine notYetParsed
396+ buildMsg [] msg = msg
401− buildMsg notYetParsed (expectation:_) msg =
397+ buildMsg (expectation:_) msg =
402− msg ++ ". Expecting " ++ expectation ++ formatErrorLine notYetParsed
398+ msg ++ ". Expecting " ++ expectation
403{-# INLINE eitherDecodeWith #-}
399{-# INLINE eitherDecodeWith #-}
404
400
405−-- | Grab the first 100 bytes from the non parsed portion and
406−-- format to get nicer error messages
407−formatErrorLine :: L.ByteString -> String
408−formatErrorLine bs =
409− C.unpack .
410− -- if formatting results in empty ByteString just return that
411− -- otherwise construct the error message with the bytestring builder
412− (\bs' ->
413− if BSL.null bs'
414− then BSL.empty
415− else
416− B.toLazyByteString $
417− B.stringUtf8 " at '" <> B.lazyByteString bs' <> B.stringUtf8 "'"
418− ) .
419− -- if newline is present cut at that position
420− BSL.takeWhile (10 /=) .
421− -- remove spaces, CR's, tabs, backslashes and quotes characters
422− BSL.filter (`notElem` [9, 13, 32, 34, 47, 92]) .
423− -- take 100 bytes
424− BSL.take 100 $ bs
425−
426eitherDecodeStrictWith :: Parser Value -> (Value -> IResult a) -> B.ByteString
401eitherDecodeStrictWith :: Parser Value -> (Value -> IResult a) -> B.ByteString
427 -> Either (JSONPath, String) a
402 -> Either (JSONPath, String) a
428eitherDecodeStrictWith p to s =
403eitherDecodeStrictWith p to s =
Data/Aeson/Types.hs−1
@@ -35,7 +35,6 @@ module Data.Aeson.Types
35 , parse
35 , parse
36 , parseEither
36 , parseEither
37 , parseMaybe
37 , parseMaybe
38− , parseFail
39 , ToJSON(..)
38 , ToJSON(..)
40 , KeyValue(..)
39 , KeyValue(..)
41 , modifyFailure
40 , modifyFailure
Data/Aeson/Types/Internal.hs+13−30
@@ -44,7 +44,6 @@ module Data.Aeson.Types.Internal
44 , parse
44 , parse
45 , parseEither
45 , parseEither
46 , parseMaybe
46 , parseMaybe
47− , parseFail
48 , modifyFailure
47 , modifyFailure
49 , prependFailure
48 , prependFailure
50 , parserThrowError
49 , parserThrowError
@@ -343,10 +342,6 @@ instance Monoid (Parser a) where
343 mappend = (<>)
342 mappend = (<>)
344 {-# INLINE mappend #-}
343 {-# INLINE mappend #-}
345
344
346−-- | Raise a parsing failure with some custom message.
347−parseFail :: String -> Parser a
348−parseFail = fail
349−
350apP :: Parser (a -> b) -> Parser a -> Parser b
345apP :: Parser (a -> b) -> Parser a -> Parser b
351apP d e = do
346apP d e = do
352 b <- d
347 b <- d
@@ -586,53 +581,41 @@ data Options = Options
586 -- the constructor tag. If 'False' the encoding will always
581 -- the constructor tag. If 'False' the encoding will always
587 -- follow the `sumEncoding`.
582 -- follow the `sumEncoding`.
588 , omitNothingFields :: Bool
583 , omitNothingFields :: Bool
589− -- ^ If 'True', record fields with a 'Nothing' value will be
584+ -- ^ If 'True' record fields with a 'Nothing' value will be
590− -- omitted from the resulting object. If 'False', the resulting
585+ -- omitted from the resulting object. If 'False' the resulting
591 -- object will include those fields mapping to @null@.
586 -- object will include those fields mapping to @null@.
592 --
587 --
593− -- Note that this /does not/ affect parsing: 'Maybe' fields are
594− -- optional regardless of the value of 'omitNothingFields', subject
595− -- to the note below.
596− --
597 -- === Note
588 -- === Note
598 --
589 --
599 -- Setting 'omitNothingFields' to 'True' only affects fields which are of
590 -- Setting 'omitNothingFields' to 'True' only affects fields which are of
600− -- type 'Maybe' /uniformly/ in the 'ToJSON' instance.
591+ -- type 'Maybe' /uniformly/ in the 'ToJSON' or 'FromJSON' instance. In
601− -- In particular, if the type of a field is declared as a type variable, it
592+ -- particular, if the type of a field is declared as a type variable, it
602 -- will not be omitted from the JSON object, unless the field is
593 -- will not be omitted from the JSON object, unless the field is
603 -- specialized upfront in the instance.
594 -- specialized upfront in the instance.
604 --
595 --
605− -- The same holds for 'Maybe' fields being optional in the 'FromJSON' instance.
606− --
607 -- ==== __Example__
596 -- ==== __Example__
608 --
597 --
609 -- The generic instance for the following type @Fruit@ depends on whether
598 -- The generic instance for the following type @Fruit@ depends on whether
610 -- the instance head is @Fruit a@ or @Fruit (Maybe a)@.
599 -- the instance head is @Fruit a@ or @Fruit (Maybe a)@.
611 --
600 --
612 -- @
601 -- @
613− -- data Fruit a = Fruit
602+ -- data Fruit a =
614 -- { apples :: a -- A field whose type is a type variable.
603 -- { apples :: a -- A field whose type is a type variable.
615 -- , oranges :: 'Maybe' Int
604 -- , oranges :: 'Maybe' Int
616− -- } deriving 'Generic'
605+ -- }
606+ --
607+ -- options :: 'Options'
608+ -- options = 'defaultOptions' { 'omitNothingFields' = 'True' }
617 --
609 --
618 -- -- apples required, oranges optional
610 -- -- apples required, oranges optional
619 -- -- Even if 'Data.Aeson.fromJSON' is then specialized to (Fruit ('Maybe' a)).
611 -- -- Even if 'Data.Aeson.fromJSON' is then specialized to (Fruit ('Maybe' a)).
620− -- instance 'Data.Aeson.FromJSON' a => 'Data.Aeson.FromJSON' (Fruit a)
612+ -- instance 'Data.Aeson.FromJSON' a => 'Data.Aeson.FromJSON' (Fruit a) where
613+ -- 'Data.Aeson.fromJSON' = 'Data.Aeson.genericFromJSON' options
621 --
614 --
622 -- -- apples optional, oranges optional
615 -- -- apples optional, oranges optional
623 -- -- In this instance, the field apples is uniformly of type ('Maybe' a).
616 -- -- In this instance, the field apples is uniformly of type ('Maybe' a).
624− -- instance 'Data.Aeson.FromJSON' a => 'Data.Aeson.FromJSON' (Fruit ('Maybe' a))
617+ -- instance 'Data.Aeson.FromJSON' a => 'Data.Aeson.FromJSON' (Fruit ('Maybe' a)) where
625− --
618+ -- 'Data.Aeson.fromJSON' = 'Data.Aeson.genericFromJSON' options
626− -- options :: 'Options'
627− -- options = 'defaultOptions' { 'omitNothingFields' = 'True' }
628− --
629− -- -- apples always present in the output, oranges is omitted if 'Nothing'
630− -- instance 'Data.Aeson.ToJSON' a => 'Data.Aeson.ToJSON' (Fruit a) where
631− -- 'Data.Aeson.toJSON' = 'Data.Aeson.genericToJSON' options
632− --
633− -- -- both apples and oranges are omitted if 'Nothing'
634− -- instance 'Data.Aeson.ToJSON' a => 'Data.Aeson.ToJSON' (Fruit ('Maybe' a)) where
635− -- 'Data.Aeson.toJSON' = 'Data.Aeson.genericToJSON' options
636 -- @
619 -- @
637 , sumEncoding :: SumEncoding
620 , sumEncoding :: SumEncoding
638 -- ^ Specifies how to encode constructors of a sum datatype.
621 -- ^ Specifies how to encode constructors of a sum datatype.