deriving-aeson 0 → 0.1
raw patch · 4 files changed
+98/−5 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Deriving.Aeson.Stock: class FromJSON a
+ Deriving.Aeson.Stock: class Generic a
+ Deriving.Aeson.Stock: class ToJSON a
+ Deriving.Aeson.Stock: type Prefixed str = CustomJSON '[FieldLabelModifier (StripPrefix str)]
+ Deriving.Aeson.Stock: type PrefixedSnake str = CustomJSON '[FieldLabelModifier (StripPrefix str, CamelToSnake)]
+ Deriving.Aeson.Stock: type Snake = CustomJSON '[FieldLabelModifier CamelToSnake]
Files
- README.md +70/−0
- deriving-aeson.cabal +5/−3
- src/Deriving/Aeson/Stock.hs +21/−0
- tests/test.hs +2/−2
+ README.md view
@@ -0,0 +1,70 @@+deriving-aeson+====++[](https://hackage.haskell.org/package/deriving-aeson)++[](https://discord.gg/DG93Tgs)++This package provides a newtype wrapper where you can customise+[aeson](https://hackage,haskell.org/package/aeson)'s generic methods using a+type-level interface, which synergises well with DerivingVia.++```haskell+{-# LANGUAGE DerivingVia, DataKinds, DeriveGeneric #-}+import Data.Aeson+import Deriving.Aeson+import qualified Data.ByteString.Lazy.Char8 as BL++data User = User+ { userId :: Int+ , userName :: String+ , userAPIToken :: Maybe String+ } deriving Generic+ deriving (FromJSON, ToJSON)+ via CustomJSON '[OmitNothingFields, FieldLabelModifier (StripPrefix "user", CamelToSnake)] User++testData :: [User]+testData = [User 42 "Alice" Nothing, User 43 "Bob" (Just "xyz")]++main = BL.putStrLn $ encode testData+-- [{"name":"Alice","id":42},{"api_token":"xyz","name":"Bob","id":43}]+```++`Deriving.Aeson.Stock` contains some aliases for even less boilerplates.++* `Prefixed str` = `CustomJSON '[FieldLabelModifier (StripPrefix str)]`+* `PrefixedSnake str` = `CustomJSON '[FieldLabelModifier (StripPrefix str, CamelToSnake)]`+* `Snake` = `CustomJSON '[FieldLabelModifier (StripPrefix str, CamelToSnake)]`++How it works+----++The wrapper type has a phantom type parameter `t`, a type-level builder of an [Option](http://hackage.haskell.org/package/aeson-1.4.6.0/docs/Data-Aeson.html#t:Options).+Type-level primitives are reduced to one `Option` by the `AesonOptions` class.++```haskell+newtype CustomJSON t a = CustomJSON { unCustomJSON :: a }++class AesonOptions xs where+ aesonOptions :: Options++instance AesonOptions xs => AesonOptions (OmitNothingFields ': xs) where+ aesonOptions = (aesonOptions @xs) { omitNothingFields = True }++...+```++You can use any (static) function for name modification by adding an instance of `StringModifier`.++```haskell+data ToLower+instance StringModifier ToLower where+ getStringModifier "" = ""+ getStringModifier (c : xs) = toLower c : xs+```++Previous studies+----++* [Type-driven safe derivation of ToJSON and FromJSON, using DerivingVia in GHC 8.6 and some type-level hacks](https://gist.github.com/konn/27c00f784dd883ec2b90eab8bc84a81d)+* [Strip prefices from JSON representation](https://gist.github.com/fumieval/5c89205d418d5f9cafac801afbe94969)
deriving-aeson.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name: deriving-aeson-version: 0+version: 0.1 synopsis: Type driven generic aeson instance customisation description: This package provides a newtype wrapper with FromJSON/ToJSON instances customisable via a phantom type parameter.@@ -12,10 +12,12 @@ maintainer: fumiexcel@gmail.com copyright: Copyright (c) 2020 Fumiaki Kinoshita category: JSON, Generics-extra-source-files: CHANGELOG.md+extra-source-files: CHANGELOG.md, README.md library- exposed-modules: Deriving.Aeson+ exposed-modules:+ Deriving.Aeson+ Deriving.Aeson.Stock build-depends: base >= 4.12 && <5, aeson hs-source-dirs: src default-language: Haskell2010
+ src/Deriving/Aeson/Stock.hs view
@@ -0,0 +1,21 @@+{-# LANGUAGE DataKinds #-}++module Deriving.Aeson.Stock+ ( Prefixed+ , PrefixedSnake+ , Snake+ -- * Reexports+ , FromJSON+ , ToJSON+ , Generic) where++import Deriving.Aeson++-- | Field names are prefixed by @str@; strip them from JSON representation+type Prefixed str = CustomJSON '[FieldLabelModifier (StripPrefix str)]++-- | Strip @str@ prefices and convert from CamelCase to snake_case+type PrefixedSnake str = CustomJSON '[FieldLabelModifier (StripPrefix str, CamelToSnake)]++-- | Convert from CamelCase to snake_case+type Snake = CustomJSON '[FieldLabelModifier CamelToSnake]
tests/test.hs view
@@ -3,8 +3,8 @@ module Main where import Data.Aeson-import qualified Data.ByteString.Lazy.Char8 as BL import Deriving.Aeson+import qualified Data.ByteString.Lazy.Char8 as BL data User = User { userId :: Int@@ -17,4 +17,4 @@ testData :: [User] testData = [User 42 "Alice" Nothing, User 43 "Bob" (Just "xyz")] -main = BL.putStrLn $ encode $ testData+main = BL.putStrLn $ encode testData