Json in Haskell
In Haskell, we can use the aeson library for JSON encoding and decoding. This library provides built-in support for working with JSON data, including custom data types.
First, let’s import the necessary modules:
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
import Data.Aeson
import Data.ByteString.Lazy (ByteString)
import qualified Data.ByteString.Lazy as B
import Data.Text (Text)
import qualified Data.Text as T
import Data.Map (Map)
import qualified Data.Map as MapWe’ll define two data types to demonstrate encoding and decoding of custom types:
data Response1 = Response1
    { page1 :: Int
    , fruits1 :: [Text]
    } deriving (Show)
data Response2 = Response2
    { page2 :: Int
    , fruits2 :: [Text]
    } deriving (Show)
instance ToJSON Response1 where
    toJSON Response1{..} = object
        [ "Page" .= page1
        , "Fruits" .= fruits1
        ]
instance FromJSON Response1 where
    parseJSON = withObject "Response1" $ \v -> Response1
        <$> v .: "Page"
        <*> v .: "Fruits"
instance ToJSON Response2 where
    toJSON Response2{..} = object
        [ "page" .= page2
        , "fruits" .= fruits2
        ]
instance FromJSON Response2 where
    parseJSON = withObject "Response2" $ \v -> Response2
        <$> v .: "page"
        <*> v .: "fruits"Now, let’s look at encoding basic data types to JSON:
main :: IO ()
main = do
    let bolB = encode True
    B.putStrLn bolB
    let intB = encode (1 :: Int)
    B.putStrLn intB
    let fltB = encode (2.34 :: Float)
    B.putStrLn fltB
    let strB = encode ("gopher" :: Text)
    B.putStrLn strBFor slices and maps, which encode to JSON arrays and objects:
    let slcD = ["apple", "peach", "pear"] :: [Text]
    let slcB = encode slcD
    B.putStrLn slcB
    let mapD = Map.fromList [("apple", 5), ("lettuce", 7)] :: Map Text Int
    let mapB = encode mapD
    B.putStrLn mapBNow, let’s encode our custom data types:
    let res1D = Response1 1 ["apple", "peach", "pear"]
    let res1B = encode res1D
    B.putStrLn res1B
    let res2D = Response2 1 ["apple", "peach", "pear"]
    let res2B = encode res2D
    B.putStrLn res2BFor decoding JSON data into Haskell values:
    let byt = "{\"num\":6.13,\"strs\":[\"a\",\"b\"]}" :: ByteString
    case decode byt of
        Just dat -> do
            putStrLn $ "Decoded: " ++ show (dat :: Map Text Value)
            case Map.lookup "num" dat of
                Just (Number n) -> print n
                _ -> putStrLn "Failed to extract num"
            case Map.lookup "strs" dat of
                Just (Array arr) -> print $ head arr
                _ -> putStrLn "Failed to extract strs"
        Nothing -> putStrLn "Failed to decode"
    let str = "{\"page\": 1, \"fruits\": [\"apple\", \"peach\"]}" :: ByteString
    case decode str of
        Just res -> do
            print (res :: Response2)
            print $ head $ fruits2 res
        Nothing -> putStrLn "Failed to decode Response2"In Haskell, we don’t have a direct equivalent to Go’s json.NewEncoder. However, we can achieve similar functionality by using B.hPutStrLn:
    let d = Map.fromList [("apple", 5), ("lettuce", 7)] :: Map Text Int
    B.hPutStrLn stdout $ encode dThis Haskell code demonstrates JSON encoding and decoding using the aeson library. It covers basic data types, custom types, and working with more complex nested structures. The aeson library provides a powerful and flexible way to work with JSON in Haskell, with support for automatic derivation of JSON instances for many types.