Parse JSON с именами полей, которые содержат зарезервированные ключевые слова

Я пытаюсь разобрать следующий JSON с помощью aeson.

{
    "data": [
        {
            "id": "34",
            "type": "link",
            "story": "foo"
        },
        {
            "id": "35",
            "type": "link",
            "story": "bar"
        }
    ]
}

Так как есть много полей, которые я хотел бы игнорировать, кажется, Мне нужно использовать дженерики GHC. Но как написать определение типа данных, которое использует ключевые слова Haskell, такие как data и type? Естественно, что следующее: 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)

Ответ 1

Вы можете написать свои собственные экземпляры FromJSON и ToJSON, не полагаясь на GHC.Generics. Это также означает, что вы можете использовать разные имена полей для представления данных и представления JSON.

Примеры экземпляров для сообщения:

{-# 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"

То же самое можно сделать для Feed. Если вам не нужно игнорировать поля, вы также можете использовать deriveJSON из Data.Aeson.TH, который принимает функцию для изменения имен полей в качестве первого аргумента.