aeson-injector 1.1.6.0 → 1.2.0.0
raw patch · 4 files changed
+40/−5 lines, 4 filesdep +attoparsecPVP ok
version bump matches the API change (PVP)
Dependencies added: attoparsec
API changes (from Hackage documentation)
+ Data.Aeson.WithField.Internal: mplus0 :: forall a. Parser a -> Parser a -> Parser a
Files
- CHANGELOG.md +5/−0
- aeson-injector.cabal +3/−1
- src/Data/Aeson/WithField.hs +7/−4
- src/Data/Aeson/WithField/Internal.hs +25/−0
CHANGELOG.md view
@@ -1,3 +1,8 @@+1.2.0.0+=======++- Fixes issue #3 with unexpected errors when injected value fails to parse.+ 1.1.6.0 =======
aeson-injector.cabal view
@@ -1,5 +1,5 @@ name: aeson-injector-version: 1.1.6.0+version: 1.2.0.0 synopsis: Injecting fields into aeson values description: It is small utility library that is intented to be used in RESTful APIs, especially with [servant](http://haskell-servant.readthedocs.io/en/stable/) and [Swagger](http://swagger.io/). Its main purpose is simple injection of fields into JSONs produced by [aeson](https://hackage.haskell.org/package/aeson) library. license: MIT@@ -29,10 +29,12 @@ exposed-modules: Data.Aeson.Unit Data.Aeson.WithField+ Data.Aeson.WithField.Internal build-depends: base >= 4.7 && < 4.17 , aeson >= 0.11 && < 1.6+ , attoparsec >= 0.14 && < 0.15 , bifunctors >= 5.2 && < 6 , deepseq >= 1.4 && < 2 , hashable >= 1.0 && < 2.0
src/Data/Aeson/WithField.hs view
@@ -4,6 +4,7 @@ {-# LANGUAGE OverloadedLists #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE PolyKinds #-}+{-# LANGUAGE Rank2Types #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TupleSections #-} {-# LANGUAGE TypeFamilies #-}@@ -166,6 +167,7 @@ import Control.Monad import Data.Aeson import Data.Aeson.Types (typeMismatch)+import Data.Aeson.WithField.Internal import Data.Hashable import Data.Monoid import Data.Proxy@@ -245,7 +247,7 @@ -- Note: The instance tries to parse the `b` part without `s` field at first time. -- If it fails, the instance retries with presence of the `s` field. instance (KnownSymbol s, FromJSON a, FromJSON b) => FromJSON (WithField s a b) where- parseJSON val@(Object o) = injected <|> wrapper+ parseJSON val@(Object o) = injected `mplus0` wrapper where field = T.pack $ symbolVal (Proxy :: Proxy s) injected = WithField@@ -357,10 +359,10 @@ -- that `fromJSON . toJSON === id` for `a`. instance (ToJSON a, FromJSON a, FromJSON b) => FromJSON (WithFields a b) where parseJSON val@(Object o) = do- (a, isInjected) <- ((, False) <$> parseJSON val) <|> ((, True) <$> (o .: "injected"))+ (a, isInjected) <- ((, False) <$> parseJSON val) `mplus0` ((, True) <$> (o .: "injected")) let o' = (if isInjected then H.delete "injected" else deleteAll (extractFields a)) o- b <- (parseJSON (Object o') <|> o' .: "value")- <|> (parseJSON val <|> o .: "value")+ b <- ((parseJSON (Object o')) `mplus0` (o' .: "value"))+ <|> ((parseJSON val) `mplus0` (o .: "value")) pure $ WithFields a b where deleteAll :: (Eq k, Hashable k) => [k] -> H.HashMap k v -> H.HashMap k v@@ -443,3 +445,4 @@ & required .~ [field] where field = T.pack $ symbolVal (Proxy :: Proxy s)+
+ src/Data/Aeson/WithField/Internal.hs view
@@ -0,0 +1,25 @@+{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+module Data.Aeson.WithField.Internal+ ( mplus0+ ) where++import Data.Aeson.Types (Parser, JSONPath)++import Unsafe.Coerce++newtype P a = P + { runP :: forall f r.+ JSONPath+ -> Failure f r+ -> Success a f r+ -> f r }++type Failure f r = JSONPath -> String -> f r+type Success a f r = a -> f r++mplus0 :: forall a . Parser a -> Parser a -> Parser a+mplus0 a b = unsafeCoerce @(P a) $ P $ \path kf ks -> + let kf' p l = runP (unsafeCoerce b) path (\_ _ -> kf p l) ks+ in runP (unsafeCoerce a) path kf' ks