aeson-possible 0.1.0.1 → 0.1.1.0
raw patch · 4 files changed
+69/−12 lines, 4 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Data.Aeson.Possible: instance GHC.Base.Alternative Data.Aeson.Possible.Possible
- Data.Aeson.Possible: instance GHC.Base.Applicative Data.Aeson.Possible.Possible
- Data.Aeson.Possible: instance GHC.Base.Functor Data.Aeson.Possible.Possible
- Data.Aeson.Possible: instance GHC.Generics.Generic (Data.Aeson.Possible.Possible a)
- Data.Aeson.Possible: instance GHC.Show.Show a => GHC.Show.Show (Data.Aeson.Possible.Possible a)
+ Data.Aeson.Possible: fromMaybe :: Possible a -> Maybe a -> Possible a
+ Data.Aeson.Possible: fromMaybeMissing :: Maybe a -> Possible a
+ Data.Aeson.Possible: fromMaybeNull :: Maybe a -> Possible a
+ Data.Aeson.Possible: instance GHC.Internal.Base.Alternative Data.Aeson.Possible.Possible
+ Data.Aeson.Possible: instance GHC.Internal.Base.Applicative Data.Aeson.Possible.Possible
+ Data.Aeson.Possible: instance GHC.Internal.Base.Functor Data.Aeson.Possible.Possible
+ Data.Aeson.Possible: instance GHC.Internal.Generics.Generic (Data.Aeson.Possible.Possible a)
+ Data.Aeson.Possible: instance GHC.Internal.Show.Show a => GHC.Internal.Show.Show (Data.Aeson.Possible.Possible a)
+ Data.Aeson.Possible: toMaybeMaybe :: Possible a -> Maybe (Maybe a)
Files
- CHANGELOG.md +6/−0
- aeson-possible.cabal +3/−1
- src/Data/Aeson/Possible.hs +47/−10
- test/Main.hs +13/−1
CHANGELOG.md view
@@ -1,5 +1,11 @@ # Revision history for aeson-possible +## 0.1.1.0 -- 2025-12-04++* Add more utility functions for conversions+* Tests and documentation improvements+* Expand GHC versions tested against+ ## 0.1.0.1 -- 2024-06-27 * Fix errors in documentation on use of Aeson `Options`
aeson-possible.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: aeson-possible-version: 0.1.0.1+version: 0.1.1.0 synopsis: Possible values for aeson description: Three-valued possible types for use with aeson. Useful for use in PATCH endpoints.@@ -16,6 +16,8 @@ GHC == 9.4 || == 9.6 || == 9.8+ || == 9.10+ || == 9.12 common extensions default-extensions:
src/Data/Aeson/Possible.hs view
@@ -1,5 +1,5 @@ {- |-Three-valued possible types for use with `aeson`.+Three-valued possible types for use with [aeson](https://hackage.haskell.org/package/aeson) Useful for use in PATCH endpoints: use in records which have 'ToJSON' and 'FromJSON' instances.@@ -22,8 +22,22 @@ -} module Data.Aeson.Possible ( Possible (..),- toMaybe,++ -- * Utility functions++ -- ** Equivalent expressiveness++ -- | Keep the same level of expressiveness using nested @Maybe@s+ toMaybeMaybe, fromMaybeMaybe,++ -- ** With different expressiveness++ -- | Helpers that either inject extra meaning ('fromMaybe'), or lose it ('toMaybe').+ toMaybe,+ fromMaybe,+ fromMaybeNull,+ fromMaybeMissing, ) where import Control.Applicative@@ -58,12 +72,12 @@ Missing <|> r = r l@(HaveData _) <|> _ = l -{- | Uses 'toMaybe' to implement `toJSON` and `toEncoding`, and `aeson`'s+{- | Uses 'toMaybe' to implement @toJSON@ and @toEncoding@, and @aeson@'s 'omitField' to specify when the field should be left out. /Note/ that unless the 'Possible' value is encoded as an object field it-will be `null` even when you have a 'Missing' value.-_e.g._ `[Missing, HaveNull, HaveData 42]` will be encoded as `[null,null,42]`+will be @null@ even when you have a 'Missing' value.+_e.g._ @[Missing, HaveNull, HaveData 42]@ will be encoded as @[null,null,42]@ -} instance (ToJSON a) => ToJSON (Possible a) where toJSON = toJSON . toMaybe@@ -72,18 +86,41 @@ omitField HaveNull = False omitField (HaveData _) = False --- | Uses `omittedField` to default to 'Missing'+-- | Uses @omittedField@ to default to 'Missing' instance (FromJSON a) => FromJSON (Possible a) where parseJSON Null = pure HaveNull parseJSON v = fmap pure . parseJSON $ v omittedField = Just Missing -toMaybe :: Possible a -> Maybe a-toMaybe Missing = Nothing-toMaybe HaveNull = Nothing-toMaybe (HaveData a) = Just a+toMaybeMaybe :: Possible a -> Maybe (Maybe a)+toMaybeMaybe Missing = Nothing+toMaybeMaybe HaveNull = Just Nothing+toMaybeMaybe (HaveData a) = Just (Just a) fromMaybeMaybe :: Maybe (Maybe a) -> Possible a fromMaybeMaybe Nothing = Missing fromMaybeMaybe (Just Nothing) = HaveNull fromMaybeMaybe (Just (Just a)) = HaveData a++toMaybe :: Possible a -> Maybe a+toMaybe Missing = Nothing+toMaybe HaveNull = Nothing+toMaybe (HaveData a) = Just a++{- | Analogous to @Maybe@'s @fromMaybe@: first parameter is a default to use, for example:++> fromMaybe HaveNull p++/Note:/ You can use @fromMaybe (HaveData a)@, even though that is not the intended usage.+-}+fromMaybe :: Possible a -> Maybe a -> Possible a+fromMaybe def Nothing = def+fromMaybe _ (Just a) = HaveData a++-- | @Nothing@ becomes 'HaveNull'+fromMaybeNull :: Maybe a -> Possible a+fromMaybeNull = fromMaybe HaveNull++-- | @Nothing@ becomes 'Missing'+fromMaybeMissing :: Maybe a -> Possible a+fromMaybeMissing = fromMaybe Missing
test/Main.hs view
@@ -18,7 +18,7 @@ main = defaultMain tests tests :: TestTree-tests = testGroup "Tests" [laws, unitTests]+tests = testGroup "Tests" [laws, unitTests, helperTests] newtype A_Possible a = A_Possible {unwrap :: Possible a} deriving stock (Show, Generic, Functor)@@ -109,4 +109,16 @@ , testCase "Decode value" $ eitherDecode "true" @?= Right (HaveData True) ]+ ]++helperTests :: TestTree+helperTests =+ testGroup+ "Test helpers"+ [ QC.testProperty "Maybe Maybe two-way" $ \(p' :: A_Possible Bool) ->+ let p = unwrap p'+ in p === fromMaybeMaybe (toMaybeMaybe p)+ , QC.testProperty "Single Maybe two-way with default" $ \(p' :: A_Possible Bool) ->+ let p = unwrap p'+ in p === fromMaybe p (toMaybe p) ]