3-- Copyright: (c) 2011-2016 Bryan O'Sullivan
4-- (c) 2011 MailRank, Inc.
6-- Maintainer: Bryan O'Sullivan <bos@serpentine.com>
7-- Stability: experimental
8-- Portability: portable
10-- Types and functions for working efficiently with JSON data.
12-- (A note on naming: in Greek mythology, Aeson was the father of Jason.)
16 -- * How to use this library
19 -- ** Writing instances by hand
22 -- ** Working with the AST
25 -- ** Decoding to a Haskell value
28 -- ** Decoding a mixed-type object
31 -- * Encoding and decoding
32 -- $encoding_and_decoding
41 -- ** Variants for strict bytestrings
52 -- * Convenience types
62 , ToJSONKeyFunction(..)
64 , FromJSONKeyFunction(..)
65 -- ** Liftings to unary and binary type constructors
76 -- ** Generic JSON classes and options
87 , genericLiftToEncoding
89 , genericLiftParseJSON
90 -- ** Generic and TH encoding configuration
96 , constructorTagModifier
97 , allNullaryToStringTag
101 , tagSingleConstructors
102 -- *** Options utilities
105 , defaultTaggedObject
107 -- * Inspecting @'Value's@
114 -- * Constructors and accessors
131import Data.Aeson.Types.FromJSON (ifromJSON)
132import Data.Aeson.Encoding (encodingToLazyByteString)
133import Data.Aeson.Parser.Internal (decodeWith, decodeStrictWith, eitherDecodeWith, eitherDecodeStrictWith, jsonEOF, json, jsonEOF', json')
134import Data.Aeson.Types
135import Data.Aeson.Types.Internal (JSONPath, formatError)
136import qualified Data.ByteString as B
137import qualified Data.ByteString.Lazy as L
139-- | Efficiently serialize a JSON value as a lazy 'L.ByteString'.
141-- This is implemented in terms of the 'ToJSON' class's 'toEncoding' method.
142encode :: (ToJSON a) => a -> L.ByteString
143encode = encodingToLazyByteString . toEncoding
145-- | Efficiently deserialize a JSON value from a lazy 'L.ByteString'.
146-- If this fails due to incomplete or invalid input, 'Nothing' is
149-- The input must consist solely of a JSON document, with no trailing
150-- data except for whitespace.
152-- This function parses immediately, but defers conversion. See
153-- 'json' for details.
154decode :: (FromJSON a) => L.ByteString -> Maybe a
155decode = decodeWith jsonEOF fromJSON
158-- | Efficiently deserialize a JSON value from a strict 'B.ByteString'.
159-- If this fails due to incomplete or invalid input, 'Nothing' is
162-- The input must consist solely of a JSON document, with no trailing
163-- data except for whitespace.
165-- This function parses immediately, but defers conversion. See
166-- 'json' for details.
167decodeStrict :: (FromJSON a) => B.ByteString -> Maybe a
168decodeStrict = decodeStrictWith jsonEOF fromJSON
169{-# INLINE decodeStrict #-}
171-- | Efficiently deserialize a JSON value from a lazy 'L.ByteString'.
172-- If this fails due to incomplete or invalid input, 'Nothing' is
175-- The input must consist solely of a JSON document, with no trailing
176-- data except for whitespace.
178-- This function parses and performs conversion immediately. See
179-- 'json'' for details.
180decode' :: (FromJSON a) => L.ByteString -> Maybe a
181decode' = decodeWith jsonEOF' fromJSON
182{-# INLINE decode' #-}
184-- | Efficiently deserialize a JSON value from a strict 'B.ByteString'.
185-- If this fails due to incomplete or invalid input, 'Nothing' is
188-- The input must consist solely of a JSON document, with no trailing
189-- data except for whitespace.
191-- This function parses and performs conversion immediately. See
192-- 'json'' for details.
193decodeStrict' :: (FromJSON a) => B.ByteString -> Maybe a
194decodeStrict' = decodeStrictWith jsonEOF' fromJSON
195{-# INLINE decodeStrict' #-}
197eitherFormatError :: Either (JSONPath, String) a -> Either String a
198eitherFormatError = either (Left . uncurry formatError) Right
199{-# INLINE eitherFormatError #-}
201-- | Like 'decode' but returns an error message when decoding fails.
202eitherDecode :: (FromJSON a) => L.ByteString -> Either String a
203eitherDecode = eitherFormatError . eitherDecodeWith jsonEOF ifromJSON
204{-# INLINE eitherDecode #-}
206-- | Like 'decodeStrict' but returns an error message when decoding fails.
207eitherDecodeStrict :: (FromJSON a) => B.ByteString -> Either String a
209 eitherFormatError . eitherDecodeStrictWith jsonEOF ifromJSON
210{-# INLINE eitherDecodeStrict #-}
212-- | Like 'decode'' but returns an error message when decoding fails.
213eitherDecode' :: (FromJSON a) => L.ByteString -> Either String a
214eitherDecode' = eitherFormatError . eitherDecodeWith jsonEOF' ifromJSON
215{-# INLINE eitherDecode' #-}
217-- | Like 'decodeStrict'' but returns an error message when decoding fails.
218eitherDecodeStrict' :: (FromJSON a) => B.ByteString -> Either String a
220 eitherFormatError . eitherDecodeStrictWith jsonEOF' ifromJSON
221{-# INLINE eitherDecodeStrict' #-}
225-- This section contains basic information on the different ways to
226-- work with data using this library. These range from simple but
227-- inflexible, to complex but flexible.
229-- The most common way to use the library is to define a data type,
230-- corresponding to some JSON data you want to work with, and then
231-- write either a 'FromJSON' instance, a to 'ToJSON' instance, or both
234-- For example, given this JSON data:
236-- > { "name": "Joe", "age": 12 }
238-- we create a matching data type:
240-- > {-# LANGUAGE DeriveGeneric #-}
242-- > import GHC.Generics
244-- > data Person = Person {
247-- > } deriving (Generic, Show)
249-- The @LANGUAGE@ pragma and 'Generic' instance let us write empty
250-- 'FromJSON' and 'ToJSON' instances for which the compiler will
251-- generate sensible default implementations.
254-- instance 'ToJSON' Person where
255-- \-- No need to provide a 'toJSON' implementation.
257-- \-- For efficiency, we write a simple 'toEncoding' implementation, as
258-- \-- the default version uses 'toJSON'.
259-- 'toEncoding' = 'genericToEncoding' 'defaultOptions'
261-- instance 'FromJSON' Person
262-- \-- No need to provide a 'parseJSON' implementation.
265-- We can now encode a value like so:
267-- > >>> encode (Person {name = "Joe", age = 12})
268-- > "{\"name\":\"Joe\",\"age\":12}"
272-- When necessary, we can write 'ToJSON' and 'FromJSON' instances by
273-- hand. This is valuable when the JSON-on-the-wire and Haskell data
274-- are different or otherwise need some more carefully managed
275-- translation. Let's revisit our JSON data:
277-- > { "name": "Joe", "age": 12 }
279-- We once again create a matching data type, without bothering to add
280-- a 'Generic' instance this time:
282-- > data Person = Person {
287-- To decode data, we need to define a 'FromJSON' instance:
289-- > {-# LANGUAGE OverloadedStrings #-}
291-- > instance FromJSON Person where
292-- > parseJSON = withObject "Person" $ \v -> Person
296-- We can now parse the JSON data like so:
298-- > >>> decode "{\"name\":\"Joe\",\"age\":12}" :: Maybe Person
299-- > Just (Person {name = "Joe", age = 12})
301-- To encode data, we need to define a 'ToJSON' instance. Let's begin
302-- with an instance written entirely by hand.
305-- instance ToJSON Person where
306-- \-- this generates a 'Value'
307-- 'toJSON' (Person name age) =
308-- 'object' [\"name\" '.=' name, \"age\" '.=' age]
310-- \-- this encodes directly to a bytestring Builder
311-- 'toEncoding' (Person name age) =
312-- 'pairs' (\"name\" '.=' 'name' '<>' \"age\" '.=' age)
315-- We can now encode a value like so:
317-- > >>> encode (Person {name = "Joe", age = 12})
318-- > "{\"name\":\"Joe\",\"age\":12}"
320-- There are predefined 'FromJSON' and 'ToJSON' instances for many
321-- types. Here's an example using lists and 'Int's:
323-- > >>> decode "[1,2,3]" :: Maybe [Int]
326-- And here's an example using the 'Data.Map.Map' type to get a map of
329-- > >>> decode "{\"foo\":1,\"bar\":2}" :: Maybe (Map String Int)
330-- > Just (fromList [("bar",2),("foo",1)])
332-- While the notes below focus on decoding, you can apply almost the
333-- same techniques to /encoding/ data. (The main difference is that
334-- encoding always succeeds, but decoding has to handle the
335-- possibility of failure, where an input doesn't match our
338-- See the documentation of 'FromJSON' and 'ToJSON' for some examples
339-- of how you can automatically derive instances in many common
344-- Sometimes you want to work with JSON data directly, without first
345-- converting it to a custom data type. This can be useful if you want
346-- to e.g. convert JSON data to YAML data, without knowing what the
347-- contents of the original JSON data was. The 'Value' type, which is
348-- an instance of 'FromJSON', is used to represent an arbitrary JSON
349-- AST (abstract syntax tree). Example usage:
351-- > >>> decode "{\"foo\": 123}" :: Maybe Value
352-- > Just (Object (fromList [("foo",Number 123)]))
354-- > >>> decode "{\"foo\": [\"abc\",\"def\"]}" :: Maybe Value
355-- > Just (Object (fromList [("foo",Array (fromList [String "abc",String "def"]))]))
357-- Once you have a 'Value' you can write functions to traverse it and
358-- make arbitrary transformations.
362-- We can decode to any instance of 'FromJSON':
364-- > λ> decode "[1,2,3]" :: Maybe [Int]
367-- Alternatively, there are instances for standard data types, so you
368-- can use them directly. For example, use the 'Data.Map.Map' type to
369-- get a map of 'Int's.
371-- > λ> import Data.Map
372-- > λ> decode "{\"foo\":1,\"bar\":2}" :: Maybe (Map String Int)
373-- > Just (fromList [("bar",2),("foo",1)])
377-- The above approach with maps of course will not work for mixed-type
378-- objects that don't follow a strict schema, but there are a couple
379-- of approaches available for these.
381-- The 'Object' type contains JSON objects:
383-- > λ> decode "{\"name\":\"Dave\",\"age\":2}" :: Maybe Object
384-- > Just (fromList) [("name",String "Dave"),("age",Number 2)]
386-- You can extract values from it with a parser using 'parse',
387-- 'parseEither' or, in this example, 'parseMaybe':
389-- > λ> do result <- decode "{\"name\":\"Dave\",\"age\":2}"
390-- > flip parseMaybe result $ \obj -> do
391-- > age <- obj .: "age"
392-- > name <- obj .: "name"
393-- > return (name ++ ": " ++ show (age*2))
397-- Considering that any type that implements 'FromJSON' can be used
398-- here, this is quite a powerful way to parse JSON. See the
399-- documentation in 'FromJSON' for how to implement this class for
400-- your own data types.
402-- The downside is that you have to write the parser yourself; the
403-- upside is that you have complete control over the way the JSON is
406-- $encoding_and_decoding
408-- Decoding is a two-step process.
410-- * When decoding a value, the process is reversed: the bytes are
411-- converted to a 'Value', then the 'FromJSON' class is used to
412-- convert to the desired type.
414-- There are two ways to encode a value.
416-- * Convert to a 'Value' using 'toJSON', then possibly further
417-- encode. This was the only method available in aeson 0.9 and
420-- * Directly encode (to what will become a 'L.ByteString') using
421-- 'toEncoding'. This is much more efficient (about 3x faster, and
422-- less memory intensive besides), but is only available in aeson
425-- For convenience, the 'encode' and 'decode' functions combine both
430-- In older versions of this library, encoding a Haskell value
431-- involved converting to an intermediate 'Value', then encoding that.
433-- A \"direct\" encoder converts straight from a source Haskell value
434-- to a 'BL.ByteString' without constructing an intermediate 'Value'.
435-- This approach is faster than 'toJSON', and allocates less memory.
436-- The 'toEncoding' method makes it possible to implement direct
437-- encoding with low memory overhead.
439-- To complicate matters, the default implementation of 'toEncoding'
440-- uses 'toJSON'. Why? The 'toEncoding' method was added to this
441-- library much more recently than 'toJSON'. Using 'toJSON' ensures
442-- that packages written against older versions of this library will
443-- compile and produce correct output, but they will not see any
444-- speedup from direct encoding.
446-- To write a minimal implementation of direct encoding, your type
447-- must implement GHC's 'Generic' class, and your code should look
451-- 'toEncoding' = 'genericToEncoding' 'defaultOptions'
454-- What if you have more elaborate encoding needs? For example,
455-- perhaps you need to change the names of object keys, omit parts of
458-- To encode to a JSON \"object\", use the 'pairs' function.
461-- 'toEncoding' (Person name age) =
462-- 'pairs' (\"name\" '.=' 'name' '<>' \"age\" '.=' age)
465-- Any container type that implements 'Foldable' can be encoded to a
466-- JSON \"array\" using 'foldable'.
468-- > > import Data.Sequence as Seq
469-- > > encode (Seq.fromList [1,2,3])
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list