packages feed

aeson-via 0.1.0 → 0.1.1

raw patch · 3 files changed

+87/−7 lines, 3 filesdep +aeson-viadep +tastydep +tasty-hunitdep ~aesondep ~aeson-casingdep ~newtype-genericsPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: aeson-via, tasty, tasty-hunit

Dependency ranges changed: aeson, aeson-casing, newtype-generics, text

API changes (from Hackage documentation)

- AesonVia: instance (Control.Newtype.Generics.Newtype n, o Data.Type.Equality.~ Control.Newtype.Generics.O n, Data.Aeson.Types.FromJSON.FromJSON o) => Data.Aeson.Types.FromJSON.FromJSON (AesonVia.AesonNewtype n o)
- AesonVia: instance (Control.Newtype.Generics.Newtype n, o Data.Type.Equality.~ Control.Newtype.Generics.O n, Data.Aeson.Types.ToJSON.ToJSON o) => Data.Aeson.Types.ToJSON.ToJSON (AesonVia.AesonNewtype n o)
+ AesonVia: instance (Control.Newtype.Generics.Newtype n, o GHC.Types.~ Control.Newtype.Generics.O n, Data.Aeson.Types.FromJSON.FromJSON o) => Data.Aeson.Types.FromJSON.FromJSON (AesonVia.AesonNewtype n o)
+ AesonVia: instance (Control.Newtype.Generics.Newtype n, o GHC.Types.~ Control.Newtype.Generics.O n, Data.Aeson.Types.ToJSON.ToJSON o) => Data.Aeson.Types.ToJSON.ToJSON (AesonVia.AesonNewtype n o)

Files

aeson-via.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 60d4229649edb0ef7f1268f79df05c7fa9d34be348ef1a2d860902ccdc143242+-- hash: 318cc7b2c6d83b710b0f777d76624040eeabdc8b6851a92937edba2804dcffde  name:           aeson-via-version:        0.1.0+version:        0.1.1 synopsis:       Wrappers to derive-via Aeson ToJSON/FromJSON typeclasses description:    Please see the README on GitHub at <https://github.com/ejconlon/aeson-via#readme> category:       Data@@ -35,9 +35,28 @@       src   ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wpartial-fields -Wredundant-constraints -fno-warn-unused-top-binds   build-depends:-      aeson >=1.4-    , aeson-casing >=0.2+      aeson >=1.5 && <1.6+    , aeson-casing >=0.2 && <0.3     , base >=4.12 && <5-    , newtype-generics >=0.5-    , text >=1.2+    , newtype-generics >=0.5 && <0.6+    , text >=1.2 && <1.3+  default-language: Haskell2010++test-suite aeson-via-test+  type: exitcode-stdio-1.0+  main-is: Main.hs+  other-modules:+      Paths_aeson_via+  hs-source-dirs:+      test+  ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wpartial-fields -Wredundant-constraints -fno-warn-unused-top-binds -threaded -rtsopts -with-rtsopts=-N+  build-depends:+      aeson >=1.5 && <1.6+    , aeson-casing >=0.2 && <0.3+    , aeson-via+    , base >=4.12 && <5+    , newtype-generics >=0.5 && <0.6+    , tasty >=1.2 && <1.3+    , tasty-hunit >=0.10 && <0.11+    , text >=1.2 && <1.3   default-language: Haskell2010
src/AesonVia.hs view
@@ -2,6 +2,8 @@ {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} +-- | Wrappers to control generic 'ToJSON' and 'FromJSON' derivation with deriving-via.+--   See the test for example definitions and their encoding. module AesonVia   ( AesonRecord (..)   , AesonNewtype (..)@@ -11,7 +13,8 @@   ) where  import Control.Newtype.Generics (Newtype, O, pack, unpack)-import Data.Aeson+import Data.Aeson (FromJSON (..), GFromJSON, GToEncoding, GToJSON, Options (..), ToJSON (..), Zero, defaultOptions,+                   genericParseJSON, genericToEncoding, genericToJSON) import Data.Aeson.Casing (aesonPrefix, snakeCase) import Data.Proxy (Proxy (..)) import Data.Text (Text)@@ -39,14 +42,19 @@  -- Has classes +-- | Mostly an internal class directing constructor/field conversion. class HasJSONOptions a where   getJSONOptions :: Proxy a -> Options +-- | Used with 'AesonTag' to define a prefix to be removed from a 'Bounded' 'Enum'.+-- For example, `data Foo = FooBar | FooBaz` would use the prefix `Foo` to yield converted string+-- values `bar` and `baz`. class HasTagPrefix a where   getTagPrefix :: Proxy a -> Text  -- Wrappers +-- | Generic deriving ToJSON/FromJSON via this uses 'HasTagPrefix' to turn 'Bounded' 'Enum' datatypes into enumerated strings. newtype AesonTag a = AesonTag { unAesonTag :: a }  instance HasTagPrefix a => HasJSONOptions (AesonTag a) where@@ -59,6 +67,7 @@ instance (HasJSONOptions (AesonTag a), Generic a, GFromJSON Zero (Rep a)) => FromJSON (AesonTag a) where   parseJSON = (AesonTag <$>) . genericParseJSON (getJSONOptions (Proxy :: Proxy (AesonTag a))) +-- | Generic deriving ToJSON/FromJSON via this removes the common field name prefix in the encoding. newtype AesonRecord a = AesonRecord { unAesonRecord :: a }  instance HasJSONOptions (AesonRecord a) where@@ -71,6 +80,7 @@ instance (HasJSONOptions (AesonRecord a), Generic a, GFromJSON Zero (Rep a)) => FromJSON (AesonRecord a) where   parseJSON = (AesonRecord <$>) . genericParseJSON (getJSONOptions (Proxy :: Proxy (AesonRecord a))) +-- | Generic deriving ToJSON/FromJSON via this yields an encoding equivalent to the wrapped type. newtype AesonNewtype n o = AesonNewtype { unAesonNewtype :: n }  instance HasJSONOptions (AesonNewtype n o) where
+ test/Main.hs view
@@ -0,0 +1,51 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DerivingVia #-}+{-# LANGUAGE OverloadedStrings #-}++module Main+  ( main+  ) where++import AesonVia (AesonNewtype (..), AesonRecord (..), AesonTag (..), HasTagPrefix (..))+import Control.Newtype.Generics (Newtype)+import Data.Aeson (FromJSON, ToJSON, encode)+import qualified Data.Text.Lazy.Encoding as TLE+import GHC.Generics (Generic)+import Test.Tasty (TestTree, defaultMain, testGroup)+import Test.Tasty.HUnit (testCase, (@?=))++newtype Author = Author+  { _authorWrapped :: String+  } deriving (Eq, Show, Generic)+    deriving (ToJSON, FromJSON) via (AesonNewtype Author String)++instance Newtype Author++data Category =+    CategoryNews+  | CategoryOpinion+  | CategoryLies+  deriving (Eq, Show, Generic)+  deriving (ToJSON, FromJSON) via (AesonTag Category)++instance HasTagPrefix Category where+  getTagPrefix _ = "Category"++data Article = Article+  { _articleTitle :: String+  , _articleAuthor :: Author+  , _articleCategory :: Category+  } deriving (Eq, Show, Generic)+    deriving (ToJSON, FromJSON) via (AesonRecord Article)++testSomething :: TestTree+testSomething = testCase "something" $ do+  let article = Article "Throw the ball!" (Author "Dog") CategoryOpinion+      expected = "{\"title\":\"Throw the ball!\",\"author\":\"Dog\",\"category\":\"opinion\"}"+      actual = TLE.decodeUtf8 (encode article)+  actual @?= expected++main :: IO ()+main = defaultMain $ testGroup "AesonVia"+  [ testSomething+  ]