Commits

Bryan O'Sullivan committed 20a8f87 Merge

Merge Neill Bogie's changes

Comments (0)

Files changed (4)

Data/Aeson/Types.hs

 -- instance ToJSON Coord where
 --   toJSON (Coord x y) = 'object' [\"x\" '.=' x, \"y\" '.=' y]
 -- @
+--
+-- This example assumes the OverloadedStrings language option is enabled.
 class ToJSON a where
     toJSON   :: a -> Value
 
 --   \-- A non-'Object' value is of the wrong type, so use 'mzero' to fail.
 --   parseJSON _          = 'mzero'
 -- @
+--
+-- This example assumes the OverloadedStrings language option is enabled.
 class FromJSON a where
     parseJSON :: Value -> Parser a
 
     benchmarks/json-data/twitter100.json
     tests/Makefile
     tests/Properties.hs
+    examples/Demo.hs
 
 flag developer
   description: operate in developer mode
+{-# LANGUAGE OverloadedStrings #-}
+
+-- Simplest example of parsing and encoding JSON with Aeson.
+
+-- Above, we enable OverloadedStrings to allow a literal string (e.g. "name")
+-- to be automatically converted to Data.Text.
+-- This is useful when using Aeson's functions such as (.:) which expect Text.
+-- Without it we'd need to use pack.
+
+import Data.Aeson
+import qualified Data.Aeson.Types as T
+
+import Data.Attoparsec (parse, Result(..))
+import Data.Text (Text)
+import Control.Applicative ((<$>))
+import Control.Monad (mzero)
+import qualified Data.ByteString.Char8 as BS
+-- Aeson's "encode" to JSON generates lazy bytestrings
+import qualified Data.ByteString.Lazy.Char8 as BSL
+
+-- In main we'll parse a JSON message into a Msg and display that,
+-- then we'll encode a different Msg as JSON, and display it.
+main ::IO ()
+main = do
+  print $ parseMsgFromString exampleJSONMessage
+  let reply = Msg "hello Aeson!"
+  putStrLn $ "Encoded reply: " ++ BSL.unpack (encode reply)
+
+-- this is the type we'll be converting to and from JSON
+data Msg = Msg Text deriving (Show)
+
+-- here's how we should parse JSON and construct a Msg
+instance FromJSON Msg where
+  parseJSON (Object v) = Msg <$> v .: "message"
+  parseJSON _ = mzero
+
+-- here's how we should encode a Msg as JSON
+instance ToJSON Msg where
+  toJSON (Msg s) = object [ "message" .= s]
+
+-- Here's one way to actually run the parsers.
+--
+-- Note that we do two parses:
+-- once into JSON then one more into our final type.
+-- There are a number of choices when dealing with parse failures.
+-- Here we've chosen to parse to Maybe Msg, and a Nothing will be returned
+-- if parseJSON fails.  (More informative options are available.)
+--
+-- This should take us (depending on success or failure)
+-- from {"message": "hello world"} to Just (Msg "hello world")
+--                              or to Nothing
+--
+-- Note also that we have not checked here that the input has been completely
+-- consumed, so:
+-- {"message": "hello world"} foo BIG mistake
+-- would yield the same successfully translated message!
+-- We could look in "rest" for the remainder.
+parseMsgFromString :: String -> Maybe Msg
+parseMsgFromString s =
+  let bs = BS.pack s
+  in case parse json bs of
+       (Done rest r) -> T.parseMaybe parseJSON r :: Maybe Msg
+       _             -> Nothing
+
+-- Here's the example JSON message we're going to try to parse:
+-- {"message": "hello world"}
+-- It's a JSON object with a single pair, having key 'message', and a string value.
+-- It could have more fields and structure, but that's all we're going to parse out of it.
+exampleJSONMessage :: String
+exampleJSONMessage = "{\"message\":\"hello world\"}"

examples/Simplest.hs

+{-# LANGUAGE OverloadedStrings #-}
+
+import Control.Applicative ((<$>), (<*>))
+import Control.Monad (mzero)
+import Data.Aeson
+import qualified Data.Aeson.Types as T
+import Data.Attoparsec (parse, Result(..))
+import qualified Data.ByteString.Char8 as BS
+import qualified Data.ByteString.Lazy.Char8 as BSL
+
+main ::IO ()
+main = do
+  print $ parseFromString "{\"x\":3.0,\"y\":-1.0}"
+  let reply = Coord 123.4 20
+  putStrLn $ BSL.unpack (encode reply)
+
+data Coord = Coord { x :: Double, y :: Double } deriving (Show)
+
+instance ToJSON Coord where
+  toJSON (Coord xV yV) = object ["x" .= xV, "y" .= yV]
+
+instance FromJSON Coord where
+  parseJSON (Object v) = Coord <$>
+                          v .: "x" <*>
+                          v .: "y"
+  parseJSON _          = mzero
+
+parseFromString :: String -> Maybe Coord
+parseFromString s =
+  let bs = BS.pack s
+  in case parse json bs of
+       Done _rest res -> T.parseMaybe parseJSON res
+       _              -> Nothing