Permalink
Browse files

Update Chris's docs

  • Loading branch information...
1 parent 4a3d1a1 commit d6c61a19f395525caaa66651b1d83177fe4c02cc @bos committed Nov 20, 2012
Showing with 138 additions and 102 deletions.
  1. +138 −102 Data/Aeson.hs
View
@@ -10,13 +10,114 @@
-- Types and functions for working efficiently with JSON data.
--
-- (A note on naming: in Greek mythology, Aeson was the father of Jason.)
+
+module Data.Aeson
+ (
+ -- * How to use this library
+ -- $use
+
+ -- ** Basic use
+ -- $basic
+
+ -- ** Decoding to a Haskell value
+ -- $haskell
+
+ -- ** Decoding a mixed-type object
+ -- $mixed
+
+ -- ** Automatically decoding data types
+ -- $typeable
+
+ -- ** Pitfalls
+ -- $pitfalls
+
+ -- * Encoding and decoding
+ decode
+ , decode'
+ , eitherDecode
+ , eitherDecode'
+ , encode
+ -- * Core JSON types
+ , Value(..)
+ , Array
+ , Object
+ -- * Convenience types
+ , DotNetTime(..)
+ -- * Type conversion
+ , FromJSON(..)
+ , Result(..)
+ , fromJSON
+ , ToJSON(..)
+ -- * Inspecting @'Value's@
+ , withObject
+ , withText
+ , withArray
+ , withNumber
+ , withBool
+ -- * Constructors and accessors
+ , (.=)
+ , (.:)
+ , (.:?)
+ , (.!=)
+ , object
+ -- * Parsing
+ , json
+ , json'
+ ) where
+
+import Data.Aeson.Encode (encode)
+import Data.Aeson.Parser.Internal (decodeWith, eitherDecodeWith, json, json')
+import Data.Aeson.Types
+import qualified Data.ByteString.Lazy as L
+
+-- | Efficiently deserialize a JSON value from a lazy 'L.ByteString'.
+-- If this fails due to incomplete or invalid input, 'Nothing' is
+-- returned.
+--
+-- This function parses immediately, but defers conversion. See
+-- 'json' for details.
+decode :: (FromJSON a) => L.ByteString -> Maybe a
+decode = decodeWith json fromJSON
+{-# INLINE decode #-}
+
+-- | Efficiently deserialize a JSON value from a lazy 'L.ByteString'.
+-- If this fails due to incomplete or invalid input, 'Nothing' is
+-- returned.
+--
+-- This function parses and performs conversion immediately. See
+-- 'json'' for details.
+decode' :: (FromJSON a) => L.ByteString -> Maybe a
+decode' = decodeWith json' fromJSON
+{-# INLINE decode' #-}
+
+-- | Like 'decode' but returns an error message when decoding fails.
+eitherDecode :: (FromJSON a) => L.ByteString -> Either String a
+eitherDecode = eitherDecodeWith json fromJSON
+{-# INLINE eitherDecode #-}
+
+-- | Like 'decode'' but returns an error message when decoding fails.
+eitherDecode' :: (FromJSON a) => L.ByteString -> Either String a
+eitherDecode' = eitherDecodeWith json' fromJSON
+{-# INLINE eitherDecode' #-}
+
+-- $use
--
--- /DECODING TO AN ADT ('VALUE')/
+-- This section contains basic information on the different ways to
+-- decode data using this library. These range from simple but
+-- inflexible, to complex but flexible.
+--
+-- While the notes below focus on decoding, you can apply almost the
+-- same techniques to /encoding/ data. (The main difference is that
+-- encoding always succeeds, but decoding has to handle the
+-- possibility of failure, where an input doesn't match our
+-- expectations.)
+
+-- $basic
--
-- To parse JSON into something useful, everything goes through the
-- 'decode' function, which is polymorphic on the 'FromJSON'
--- class. For representing arbitrary JSON AST there is a 'Value' type,
--- which is an instance of 'FromJSON'. For example:
+-- class. For representing arbitrary JSON values, there is a 'Value'
+-- type, which is an instance of 'FromJSON'. For example:
--
-- > λ> decode "{\"foo\":123}" :: Maybe Value
-- > Just (Object (fromList [("foo",Number 123)]))
@@ -26,14 +127,15 @@
-- To run these examples, you need to enable @OverloadedStrings@ (in
-- GHCi you can write @:set -XOverloadedStrings@) so that you can use
-- string literals for non-'String' types. We're using (the lazy
--- version of) 'Data.ByteString.Lazy.ByteString', which requires at
+-- version of) 'Data.ByteString.Lazy.ByteString'. (This requires at
-- least version 0.9.0.4 of the bytestring package to provide the
--- 'Data.String.IsString' instance. You probably have something newer
--- than this installed.
---
--- /DECODING TO HASKELL TYPES/
+-- 'Data.String.IsString' instance. You almost certainly have a
+-- suitably recent version of the library installed.)
+
+-- $haskell
--
--- Any instance of 'FromJSON' can be specified (but see the PITFALLS section):
+-- Any instance of 'FromJSON' can be specified (but see the
+-- \"Pitfalls\" section here—"Data.Aeson#pitfalls"):
--
-- > λ> decode "[1,2,3]" :: Maybe [Int]
-- > Just [1,2,3]
@@ -45,19 +147,19 @@
-- > λ> :m + Data.Map
-- > λ> decode "{\"foo\":1,\"bar\":2}" :: Maybe (Map String Int)
-- > Just (fromList [("bar",2),("foo",1)])
+
+-- $mixed
--
--- /DECODING A HETEROGENOUS OBJECT/
---
--- The above approach with maps of course will not work for
--- heterogenous objects, so there are a couple of approaches available
--- to you.
+-- The above approach with maps of course will not work for mixed-type
+-- objects that don't follow a strict schema, but there are a couple
+-- of approaches available for these.
--
-- The 'Object' type contains JSON objects:
--
-- > λ> decode "{\"name\":\"Dave\",\"age\":2}" :: Maybe Object
-- > Just (fromList) [("name",String "Dave"),("age",Number 2)]
--
--- And you extract values from it with a parser using 'parse',
+-- You can extract values from it with a parser using 'parse',
-- 'parseEither' or, in this example, 'parseMaybe':
--
-- > λ> do result <- decode "{\"name\":\"Dave\",\"age\":2}"
@@ -73,13 +175,13 @@
-- documentation in 'FromJSON' for how to implement this class for
-- your own data types.
--
--- The downside is that you have to write the parser yourself, the
+-- The downside is that you have to write the parser yourself; the
-- upside is that you have complete control over the way the JSON is
-- parsed.
+
+-- $typeable
--
--- /DECODING CUSTOM DATA TYPES GENERICALLY WITH TYPEABLE/
---
--- If you don't want such control and would prefer the JSON be parsed
+-- If you don't want fine control and would prefer the JSON be parsed
-- to your own data types automatically according to some reasonably
-- sensible isomorphic implementation, you can use the generic parser
-- based on 'Data.Typeable.Typeable' and 'Data.Data.Data'. Switch to
@@ -97,33 +199,38 @@
-- > personName = "Chris", personAge = 123
-- > })
--
--- Be aware that the encoding might not be what you expect:
+-- Be aware that the encoding may not always be what you'd naively
+-- expect:
--
-- > λ> data Foo = Foo Int Int deriving (Data,Typeable,Show)
-- > λ> encode (Foo 1 2)
-- > "[1,2]"
--
--- So it's better to treat the 'Data.Aeson.Generic.decode' and
--- 'Data.Aeson.Generic.encode' functions as an isomorphism, but do not
--- rely or care about the actual intermediate representation.
---
--- /PITFALLS/
+-- With this approach, it's best to treat the
+-- 'Data.Aeson.Generic.decode' and 'Data.Aeson.Generic.encode'
+-- functions as an isomorphism, and not to rely upon (or care about)
+-- the specific intermediate representation.
+
+-- $pitfalls
+-- #pitfalls#
--
--- Note that the JSON standard only allows arrays or objects of things
--- at the top-level, so calling decode on a simple type will not work:
+-- For historical reasons, the JSON standard requires the outermost
+-- (topmost) value in a structure to be an array or object. Calling
+-- 'decode' on a simple type will typecheck, but will never succeed:
--
-- > λ> decode "1" :: Maybe Int
-- > Nothing
-- > λ> decode "1" :: Maybe String
-- > Nothing
--
--- So stick to objects (e.g. maps in Haskell) or arrays (lists in Haskell):
+-- So stick to objects (e.g. maps in Haskell) or arrays (lists or
+-- vectors in Haskell):
--
-- > λ> decode "[1,2,3]" :: Maybe [Int]
-- > Just [1,2,3]
--
-- Likewise, for encoding to JSON you can encode anything that's an
--- instance of 'ToJSON', which does include simple types. So beware
+-- instance of 'ToJSON', and this may include simple types. So beware
-- that this aspect of the API is not isomorphic:
--
-- > λ> encode [1,2,3]
@@ -135,76 +242,5 @@
-- > λ> decode (encode (1 :: Int)) :: Maybe Int
-- > Nothing
--
--- Alternatively see 'Data.Aeson.Parser.value' to parse non-toplevel
--- JSON values.
-
-module Data.Aeson
- (
- -- * Encoding and decoding
- decode
- , decode'
- , eitherDecode
- , eitherDecode'
- , encode
- -- * Core JSON types
- , Value(..)
- , Array
- , Object
- -- * Convenience types
- , DotNetTime(..)
- -- * Type conversion
- , FromJSON(..)
- , Result(..)
- , fromJSON
- , ToJSON(..)
- -- * Inspecting @'Value's@
- , withObject
- , withText
- , withArray
- , withNumber
- , withBool
- -- * Constructors and accessors
- , (.=)
- , (.:)
- , (.:?)
- , (.!=)
- , object
- -- * Parsing
- , json
- , json'
- ) where
-
-import Data.Aeson.Encode (encode)
-import Data.Aeson.Parser.Internal (decodeWith, eitherDecodeWith, json, json')
-import Data.Aeson.Types
-import qualified Data.ByteString.Lazy as L
-
--- | Efficiently deserialize a JSON value from a lazy 'L.ByteString'.
--- If this fails due to incomplete or invalid input, 'Nothing' is
--- returned.
---
--- This function parses immediately, but defers conversion. See
--- 'json' for details.
-decode :: (FromJSON a) => L.ByteString -> Maybe a
-decode = decodeWith json fromJSON
-{-# INLINE decode #-}
-
--- | Efficiently deserialize a JSON value from a lazy 'L.ByteString'.
--- If this fails due to incomplete or invalid input, 'Nothing' is
--- returned.
---
--- This function parses and performs conversion immediately. See
--- 'json'' for details.
-decode' :: (FromJSON a) => L.ByteString -> Maybe a
-decode' = decodeWith json' fromJSON
-{-# INLINE decode' #-}
-
--- | Like 'decode' but returns an error message when decoding fails.
-eitherDecode :: (FromJSON a) => L.ByteString -> Either String a
-eitherDecode = eitherDecodeWith json fromJSON
-{-# INLINE eitherDecode #-}
-
--- | Like 'decode'' but returns an error message when decoding fails.
-eitherDecode' :: (FromJSON a) => L.ByteString -> Either String a
-eitherDecode' = eitherDecodeWith json' fromJSON
-{-# INLINE eitherDecode' #-}
+-- Alternatively, see 'Data.Aeson.Parser.value' for functions to parse
+-- non-top-level JSON values.

0 comments on commit d6c61a1

Please sign in to comment.