JSON in response of Github Gists Rest API contains Haskell's keyword type
. But type
couldn't be used as a record field.
Thus it couldn't be used in implementation of Aeson's Generic FromJSON/ToJSON instances.
import Data.Text (Text)
import GHC.Generics (Generic)
type URL = Text
data OwnerType = User deriving (Show)
data Owner = Owner {
id :: Int,
gravatar_id :: Text,
login :: Text,
avatar_url :: Text,
events_url :: URL,
followers_url :: URL,
following_url :: URL,
gists_url :: URL,
html_url :: URL,
organizations_url :: URL,
received_events_url :: URL,
repos_url :: URL,
starred_url :: URL,
subscriptions_url :: URL,
url :: URL,
-- type :: Text,
site_admin :: Bool
} deriving (Generic, Show)
instance ToJSON Owner
instance FromJSON Owner
Question: Is there a proper approach to deal with such kind of conflicts?
We can solve this by using
TemplateHaskell
. Instead of writingToJSON
andFromJON
, we can use a specific mapping of the keys.First of all, we have to construct a name for the field that is not type, for instance:
Now we can use the
deriveJSON :: Options -> Name -> Q [Dec]
function that will construct afromJSON
andtoJSON
instance.The key here is the
Options
parameter: it contains afieldLabelModifier :: String -> String
field that can rewrite the names of the fields to the keys in JSON. We can thus here generate a function that will rewrite it.So we first construct a function
ownerFieldRename :: String -> String
:So this function acts as an identity function, except for
"owner_type"
, which is mapped on"type"
.So now we can call the
deriveJSON
function with custom options like:Or in full:
RenameUtils.hs
:MainFile.hs
:Now we obtain a JSON object with
type
as key:For a simple
fieldLabelModifier
function we do not need to write a specific function (that we have to define in a specific module), we can also use an lambda expression here:MainFile.hs
:Willem's answer may be the more appropriate one, and may fit what you want better, but here's another way, allowing you to define your non-conflicting data without having to write the ToJSON and FromJSON instances for it, defining the types
and
We can now define the following instances:
The imports and language pragmas I used: