Skip to content

Instantly share code, notes, and snippets.

@Decoherence
Last active August 29, 2015 14:16
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Decoherence/b69920b4995de3970e96 to your computer and use it in GitHub Desktop.
Save Decoherence/b69920b4995de3970e96 to your computer and use it in GitHub Desktop.
Haskell JSON: Demonstrates how to automatically derive JSON instances for easy encoding/decoding of a nested data record. Also construct lenses for easy viewing/modification of fields.
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE TemplateHaskell #-}
import Control.Lens
import Data.Aeson
import qualified Data.ByteString.Lazy.Char8 as C
import GHC.Generics
-- For production code, use Text instead of String
data Person = Person { _personName :: String
, _personAge :: Int
, _address :: Address
} deriving (Generic)
data Address = Address { _street :: String
, _city :: String
, _state :: String
, _zip :: Int
} deriving (Generic)
makeLenses ''Person
makeLenses ''Address
instance FromJSON Person
instance ToJSON Person
instance FromJSON Address
instance ToJSON Address
-- Optional Show instances for pretty printing
-- GHC can derive this for you, i.e. Person {..} deriving (Show, Generic)
instance Show Person where
show (Person name age add) = "Person: " ++ name ++ ", Age: " ++ show age ++ "\nAddress: " ++ show add
instance Show Address where
show (Address str cty st zipc) = str ++ " ↩ " ++ cty ++ ", " ++ st ++ " ↩ " ++ show zipc
chris :: Person
chris = Person "Christopher" 30 (Address "27 Main St" "Rome" "GA" 30161)
main :: IO ()
main = do
putStrLn "★ Haskell Person record:"
print chris
putStrLn "\n★ Person encoded as JSON:"
C.putStrLn (encode chris)
putStrLn "\n★ Decoding JSON:"
case (decode (encode chris) :: Maybe Person) of
Just p -> print p
Nothing -> putStrLn "Failed to decode."
putStrLn "\n★ Lenses are so very useful:"
putStrLn ">Two ways to focus on the Address field:"
print $ chris ^. address -- infix notation
print $ view address chris
putStrLn "\n★ Let's modify the age using a function, and directly:"
print $ chris & personAge %~ succ -- one year wiser
print $ chris & personAge .~ 100 -- extremely wise
putStrLn "\n★ Let's change the city to Atlanta:"
print $ set (address . city) "Atlanta" chris
putStrLn "\n★ Now let's change the entire Address:"
print $ set address (Address "Secret" "Roswell" "NM" 01010) chris
putStrLn "\n★ And of course, aliens love some JSON:"
C.putStrLn $ encode $ set address (Address "Secret" "Roswell" "NM" 01010) chris
{-
λ main
★ Haskell Person record:
Person: Christopher, Age: 30
Address: 27 Main St ↩ Rome, GA ↩ 30161
★ Person encoded as JSON:
{"_personName":"Christopher","_personAge":30,"_address":{"_zip":30161,"_city":"Rome","_state":"GA","_street":"27 Main St"}}
★ Decoding JSON:
Person: Christopher, Age: 30
Address: 27 Main St ↩ Rome, GA ↩ 30161
★ Lenses are so very useful:
>Two ways to focus on the Address field:
27 Main St ↩ Rome, GA ↩ 30161
27 Main St ↩ Rome, GA ↩ 30161
★ Let's modify the age using a function, and directly:
Person: Christopher, Age: 31
Address: 27 Main St ↩ Rome, GA ↩ 30161
Person: Christopher, Age: 100
Address: 27 Main St ↩ Rome, GA ↩ 30161
★ Let's change the city to Atlanta:
Person: Christopher, Age: 30
Address: 27 Main St ↩ Atlanta, GA ↩ 30161
★ Now let's change the entire Address:
Person: Christopher, Age: 30
Address: Secret ↩ Roswell, NM ↩ 1010
★ And of course, aliens love some JSON:
{"_personName":"Christopher","_personAge":30,"_address":{"_zip":1010,"_city":"Roswell","_state":"NM","_street":"Secret"}}
-}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment