Parse JSON with fieldnames that contain reserved keywords

aeson, haskell

Solution

You can write your own `FromJSON` and `ToJSON` instances without relying on GHC.Generics. This also means that you can use different field names for the data representation and the JSON representation.

Example instances for Post:

{-# LANGUAGE OverloadedStrings #-}
import Control.Applicative
import Data.Aeson
import qualified Data.ByteString.Lazy as LBS

data Post = Post {
        postId :: String,
        typ :: String,
        story :: String
  }
  deriving (Show)

instance FromJSON Post where
  parseJSON (Object x) = Post <$> x .: "id" <*> x.: "type" <*> x .: "story"
  parseJSON _ = fail "Expected an Object"

instance ToJSON Post where
  toJSON post = object 
    [ "id" .= postId post
    , "type" .= typ post
    , "story" .= story post
    ]

main :: IO ()
main = do
  print $ (decode $ Post "{\"type\": \"myType\", \"story\": \"Really interresting story\", \"id\" : \"SomeId\"}" :: Maybe Post)
  LBS.putStrLn $ encode $ Post "myId" "myType" "Some other story"

The same can be done for Feed. If you didn't have to ignore fields, you could also use `deriveJSON` from `Data.Aeson.TH`, which takes a function to modify field names as it's first argument.

Problem

I'm trying to parse the following JSON with aeson. ``` { "data": [ { "id": "34", "type": "link", "story": "foo" }, { "id": "35", "type": "link", "story": "bar" } ] } ``` Since there are a lot of field I'd like to ignore, it seems I should use GHC generics. But how to write a data type definition that uses Haskell keywords like `data` and `type`? The following of course gives: `parse error on input `data'` ``` data Feed = Feed {data :: [Post]} deriving (Show, Generic) data Post = Post { id :: String, type :: String, story :: String } deriving (Show, Generic) ```

Original source

Related problems