deriving-aeson

Type driven generic aeson instance customisation

LTS Haskell 22.37:0.2.9@rev:1
Stackage Nightly 2024-10-06:0.2.9@rev:1
Latest on Hackage:0.2.9@rev:1

See all snapshots deriving-aeson appears in

BSD-3-Clause licensed by Fumiaki Kinoshita
Maintained by [email protected]
This version can be pinned in stack with:deriving-aeson-0.2.9@sha256:957bd6da5a4f40f74ea8c485084c3e48dd9278073f95809f068b02bdcf9c3892,1356

Module documentation for 0.2.9

Depends on 2 packages(full list with versions):
Used by 1 package in lts-21.11(full list with versions):

deriving-aeson

Hackage Haskell CI Discord

logo

This package provides a newtype wrapper where you can customise aeson’s generic methods using a type-level interface, which synergises well with DerivingVia.

{-# 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]]
  • Vanilla = CustomJSON '[]

How it works

The wrapper type has a phantom type parameter t, a type-level builder of an Option. Type-level primitives are reduced to one Option by the AesonOptions class.

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.

data ToLower
instance StringModifier ToLower where
  getStringModifier "" = ""
  getStringModifier (c : xs) = toLower c : xs

Previous studies

Changes

Revision history for deriving-aeson

0.2.9

  • Fixed a bug in chaining ConstructorTagModifier & FieldLabelModifier

0.2.8

  • Supported GHC 9.2
  • Supported aeson-2.0

0.2.7

  • Added a StringModifier instance to a list of types
  • Added Rename :: Symbol -> Symbol -> Type

0.2.6

  • Added StringModifier instances to 3 and 4-tuples
  • Fixed the bug making SumTwoElemArray point ObjectWithSingleField

0.2.5

  • Added a generic CamelTo constructor

0.2.4

  • Added RejectUnknownFields

0.2.3

  • Fixed a bug in SumTaggedObject

0.2.2

  • Added UnwrapUnaryRecords

0.2.1

  • Remove redundant type variables from Sum*

0.2

  • Added Sum* for changing the encoding of variants
  • Added Vanilla = CustomJSON '[]
  • Renamed ContructorTagModifier to ConstructorTagModifier
  • Added toEncoding implementation to CustomJSON

0.1.2

  • Reexported CustomJSON(..) from Deriving.Aeson.Stock

0.1.1

  • Added Deriving.Aeson.Stock

0 – 2020-02-26

  • First version. Released on an unsuspecting world.