aeson-deriving 0.1.0.0 → 0.1.1
raw patch · 8 files changed
+75/−6 lines, 8 filesdep +regex-tdfaPVP ok
version bump matches the API change (PVP)
Dependencies added: regex-tdfa
API changes (from Hackage documentation)
+ Data.Aeson.Deriving: data TextWithPattern (regex :: Symbol)
+ Data.Aeson.Deriving.Generic: data FirstChar a
+ Data.Aeson.Deriving.Internal.Generic: data FirstChar a
+ Data.Aeson.Deriving.Internal.Generic: instance forall k (a :: k). Data.Aeson.Deriving.Internal.Generic.StringFunction a => Data.Aeson.Deriving.Internal.Generic.StringFunction (Data.Aeson.Deriving.Internal.Generic.FirstChar a)
Files
- ChangeLog.md +8/−4
- aeson-deriving.cabal +6/−2
- src/Data/Aeson/Deriving.hs +1/−0
- src/Data/Aeson/Deriving/Generic.hs +1/−0
- src/Data/Aeson/Deriving/Internal/Generic.hs +6/−0
- src/Data/Aeson/Deriving/Text.hs +5/−0
- src/Data/Aeson/Deriving/Text/Unsafe.hs +17/−0
- test/Main.hs +31/−0
ChangeLog.md view
@@ -1,7 +1,11 @@ # Changelog for aeson-deriving -## Unreleased changes+# Revision history for servant-openapi - * A newtype for encoding Aeson's generic Options type- * A newtype for sums of records- * A newtype for nesting the encoding under a single field+### 0.1.1++* Added newtype for Text validated against a regex pattern [PR 2](https://github.com/fieldstrength/aeson-deriving/pull/2)++## 0.1.0++* First version. Released on an unsuspecting world.
aeson-deriving.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: bd8e2b4289bac4670675ad3e5d5307767ea3ad1d4a053a709b95767944b84df0+-- hash: 10c4d376657004b7575f0a910fbcb4dd80c3a284e99343ca3f3e962eeba7cd0e name: aeson-deriving-version: 0.1.0.0+version: 0.1.1 synopsis: data types for compositional, type-directed serialization description: Please see the README on GitHub at <https://github.com/fieldstrength/aeson-deriving#readme> category: Serialization@@ -39,6 +39,8 @@ Data.Aeson.Deriving.Utils Data.Aeson.Deriving.WithConstantFields other-modules:+ Data.Aeson.Deriving.Text+ Data.Aeson.Deriving.Text.Unsafe Paths_aeson_deriving hs-source-dirs: src@@ -47,6 +49,7 @@ build-depends: aeson >=1.2 && <1.5 , base >=4.7 && <5+ , regex-tdfa , text , unordered-containers default-language: Haskell2010@@ -65,6 +68,7 @@ , aeson-deriving , base >=4.7 && <5 , hedgehog+ , regex-tdfa , text , unordered-containers default-language: Haskell2010
src/Data/Aeson/Deriving.hs view
@@ -4,4 +4,5 @@ import Data.Aeson.Deriving.Known as AllExports import Data.Aeson.Deriving.ModifyField as AllExports import Data.Aeson.Deriving.SingleFieldObject as AllExports+import Data.Aeson.Deriving.Text as AllExports import Data.Aeson.Deriving.WithConstantFields as AllExports
src/Data/Aeson/Deriving/Generic.hs view
@@ -31,6 +31,7 @@ , SnakeCase , Uppercase , Lowercase+ , FirstChar , DropLowercasePrefix , DropPrefix , DropSuffix
src/Data/Aeson/Deriving/Internal/Generic.hs view
@@ -304,6 +304,7 @@ data SnakeCase data Uppercase data Lowercase+data FirstChar a -- | Applies 'dropLowercasePrefix', dropping until the first uppercase character. data DropLowercasePrefix data DropPrefix (str :: Symbol)@@ -328,6 +329,11 @@ stringFunction Proxy x | x == symbolVal (Proxy @a) = symbolVal (Proxy @b) | otherwise = x++instance StringFunction a => StringFunction (FirstChar a) where+ stringFunction Proxy = \case+ [] -> []+ c:cs -> stringFunction (Proxy @a) [c] ++ cs ------------------------------------------------------------------------------------------ -- Sum type encodings
+ src/Data/Aeson/Deriving/Text.hs view
@@ -0,0 +1,5 @@+module Data.Aeson.Deriving.Text+ ( TextWithPattern+ ) where++import Data.Aeson.Deriving.Text.Unsafe (TextWithPattern)
+ src/Data/Aeson/Deriving/Text/Unsafe.hs view
@@ -0,0 +1,17 @@+module Data.Aeson.Deriving.Text.Unsafe where++import Control.Monad (unless)+import Data.Aeson+import Data.Proxy+import Data.Text (Text, unpack)+import Text.Regex.TDFA ((=~))+import GHC.TypeLits (KnownSymbol, Symbol, symbolVal)++newtype TextWithPattern (regex :: Symbol) = TextWithPattern Text+ deriving newtype (ToJSON)++instance KnownSymbol regex => FromJSON (TextWithPattern regex) where+ parseJSON = withText "Text" $ \s ->+ TextWithPattern s <$ unless (unpack s =~ (symbolVal $ Proxy @regex)) (fail errorMsg)+ where+ errorMsg = "must match regex " <> (symbolVal $ Proxy @regex)
test/Main.hs view
@@ -8,6 +8,9 @@ import Data.Aeson import Data.Aeson.Deriving+import Data.Foldable (for_)+import Data.Aeson.Deriving.Text.Unsafe+import Data.Text import GHC.Generics import Hedgehog import Hedgehog.Main (defaultMain)@@ -186,3 +189,31 @@ tripping (Reserved "Sen" 9 'x') encode decode Just (Reserved "Sen" 9 'x') === decode "{\"control\":\"x\",\"module\":9,\"type\":\"Sen\"}"++newtype DashSeparatedWords = DashSeparatedWords Text+ deriving stock (Generic, Show, Eq)+ deriving (FromJSON, ToJSON) via TextWithPattern "^([A-Za-z]+-)*[A-Za-z]+$"++prop_accepts_matches :: Property+prop_accepts_matches = once . property $ do+ tripping (DashSeparatedWords "foo-bar-baz") encode decode+ Just (DashSeparatedWords "foo-bar-baz") === decode "\"foo-bar-baz\""++prop_rejects_non_matches :: Property+prop_rejects_non_matches = once . property $ do+ Left "Error in $: must match regex ^([A-Za-z]+-)*[A-Za-z]+$" === eitherDecode @DashSeparatedWords "\"foo.42\""+++data Heavy = BlackHole | NeutronStar+ deriving stock (Generic, Show, Eq, Ord, Bounded, Enum)+ deriving (FromJSON, ToJSON) via GenericEncoded '[ConstructorTagModifier := FirstChar Lowercase] Heavy++prop_first_char_modifier_encodes_as_expected :: Property+prop_first_char_modifier_encodes_as_expected = once . property $ do+ encode BlackHole === "\"blackHole\""+ encode NeutronStar === "\"neutronStar\""++prop_first_char_modifier_decodes_as_expected :: Property+prop_first_char_modifier_decodes_as_expected = once . property $ do+ for_ [BlackHole ..] $ \x ->+ tripping x encode decode