Please note that the issue described below doesn't happen in aeson 1.4.7
(stack LTS-16.31
). This could be something related to ghc 9.2.7
perhaps.
I have noticed that if I define a simple record in aeson
and then import it, the record "code" tag is now malformed as "body" in encode
output. It happens only when importing as a module.
First, a simple module Test1
:
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell,DeriveGeneric #-}
{-# LANGUAGE Strict #-}
module Test1
where
import Data.Aeson.TH
import Data.Aeson
import GHC.Generics
import qualified Data.Text as T (Text)
data Rsp = Rsp { code::Int, tag :: T.Text, body:: T.Text } deriving (Show,Eq,Ord)
deriveJSON defaultOptions '' Rsp
Now, if I import the module in ghci
and encode
Rsp
- "code" tag is now encoded as "body" tag which appears twice instead of once:
ghci> import Test1
ghci> import Data.Aeson (encode)
ghci> encode $ Rsp (1::Int) "nyi" ""
"{\"body\":1,\"tag\":\"nyi\",\"body\":\"\"}"
I found this when debugging migration issues for migrating from aeson 1.4.7.1
(on ghc 8.8.4
via Stack LTS-16.31
) to aeson 2.0.3.0
(on ghc 9.2.7
via Stack LTS-20.13
). It doesn't happen if instead of importing the module, I directly load Test1.hs
code in ghci.
If I remove Strict
pragma, the issue seems to go away. Perhaps something is going on here that is new to ghc 9.2+
or template haskell derivation in aeson
?
This is a bug that is already fixed in 2.1.1.0
as noted in changelog:
Use unsafeDupablePerformIO instead of incorrect accursedUnutterablePerformIO in creation of keys in TH serialisation. This fixes a bug in TH deriving, e.g. when Strict pragma was enabled.
So it seems any LTS
that has aeson
pre 2.1.1.0
is unusable if template haskell derivation is enabled for aeson
which I suspect is the case for lot of us.