Skip to content

Commit 6b68815

Browse files
committed
Reword comments about FromJSON and ToJSON
1 parent 253f1b9 commit 6b68815

File tree

2 files changed

+83
-42
lines changed

2 files changed

+83
-42
lines changed

Data/Aeson/Types/FromJSON.hs

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -281,12 +281,12 @@ genericLiftParseJSON opts pj pjl = fmap to1 . gParseJSON opts (From1Args pj pjl)
281281
--
282282
-- The basic ways to signal a failed conversion are as follows:
283283
--
284-
-- * 'empty' and 'mzero' work, but are terse and uninformative
284+
-- * 'empty' and 'mzero' work, but are terse and uninformative;
285285
--
286-
-- * 'fail' yields a custom error message
286+
-- * 'fail' yields a custom error message;
287287
--
288288
-- * 'typeMismatch' produces an informative message for cases when the
289-
-- value encountered is not of the expected type
289+
-- value encountered is not of the expected type.
290290
--
291291
-- An example type and instance using 'typeMismatch':
292292
--
@@ -296,27 +296,27 @@ genericLiftParseJSON opts pj pjl = fmap to1 . gParseJSON opts (From1Args pj pjl)
296296
--
297297
-- data Coord = Coord { x :: Double, y :: Double }
298298
--
299-
-- instance FromJSON Coord where
300-
-- parseJSON ('Object' v) = Coord
301-
-- '<$>' v '.:' \"x\"
299+
-- instance 'FromJSON' Coord where
300+
-- 'parseJSON' ('Object' v) = Coord
301+
-- '<$>' v '.:' \"x\"
302302
-- '<*>' v '.:' \"y\"
303303
--
304304
-- \-- We do not expect a non-'Object' value here.
305305
-- \-- We could use 'mzero' to fail, but 'typeMismatch'
306306
-- \-- gives a much more informative error message.
307-
-- parseJSON invalid = 'typeMismatch' \"Coord\" invalid
307+
-- 'parseJSON' invalid = 'typeMismatch' \"Coord\" invalid
308308
-- @
309309
--
310310
-- For this common case of only being concerned with a single
311-
-- type of JSON value, the functions @withObject@, @withNumber@, etc.
311+
-- type of JSON value, the functions 'withObject', 'withNumber', etc.
312312
-- are provided. Their use is to be preferred when possible, since
313-
-- they are more terse. Using @withObject@, we can rewrite the above instance
313+
-- they are more terse. Using 'withObject', we can rewrite the above instance
314314
-- (assuming the same language extension and data type) as:
315315
--
316316
-- @
317-
-- instance FromJSON Coord where
318-
-- parseJSON = withObject \"Coord\" $ \v -> Coord
319-
-- '<$>' v '.:' \"x\"
317+
-- instance 'FromJSON' Coord where
318+
-- 'parseJSON' = 'withObject' \"Coord\" $ \v -> Coord
319+
-- '<$>' v '.:' \"x\"
320320
-- '<*>' v '.:' \"y\"
321321
-- @
322322
--
@@ -325,7 +325,7 @@ genericLiftParseJSON opts pj pjl = fmap to1 . gParseJSON opts (From1Args pj pjl)
325325
--
326326
-- * "Data.Aeson.TH" provides Template Haskell functions which will derive an
327327
-- instance at compile time. The generated instance is optimized for your type
328-
-- so will probably be more efficient than the following two options:
328+
-- so it will probably be more efficient than the following option.
329329
--
330330
-- * The compiler can provide a default generic implementation for
331331
-- 'parseJSON'.
@@ -343,18 +343,21 @@ genericLiftParseJSON opts pj pjl = fmap to1 . gParseJSON opts (From1Args pj pjl)
343343
--
344344
-- data Coord = Coord { x :: Double, y :: Double } deriving 'Generic'
345345
--
346-
-- instance FromJSON Coord
346+
-- instance 'FromJSON' Coord
347347
-- @
348348
--
349-
-- If @DefaultSignatures@ doesn't give exactly the results you want,
349+
-- If the default implementation doesn't give exactly the results you want,
350350
-- you can customize the generic decoding with only a tiny amount of
351351
-- effort, using 'genericParseJSON' with your preferred 'Options':
352352
--
353353
-- @
354-
-- instance FromJSON Coord where
355-
-- parseJSON = 'genericParseJSON' 'defaultOptions'
354+
-- customOptions = 'defaultOptions'
355+
-- { 'fieldLabelModifier' = 'map' 'Data.Char.toUpper'
356+
-- }
357+
--
358+
-- instance 'FromJSON' Coord where
359+
-- 'parseJSON' = 'genericParseJSON' customOptions
356360
-- @
357-
358361
class FromJSON a where
359362
parseJSON :: Value -> Parser a
360363

@@ -516,7 +519,7 @@ typeMismatch expected actual =
516519
--
517520
-- * "Data.Aeson.TH" provides Template Haskell functions which will derive an
518521
-- instance at compile time. The generated instance is optimized for your type
519-
-- so will probably be more efficient than the following two options:
522+
-- so it will probably be more efficient than the following option.
520523
--
521524
-- * The compiler can provide a default generic implementation for
522525
-- 'liftParseJSON'.
@@ -534,16 +537,20 @@ typeMismatch expected actual =
534537
--
535538
-- data Pair a b = Pair { pairFst :: a, pairSnd :: b } deriving 'Generic1'
536539
--
537-
-- instance FromJSON a => FromJSON1 (Pair a)
540+
-- instance 'FromJSON' a => 'FromJSON1' (Pair a)
538541
-- @
539542
--
540-
-- If @DefaultSignatures@ doesn't give exactly the results you want,
543+
-- If the default implementation doesn't give exactly the results you want,
541544
-- you can customize the generic decoding with only a tiny amount of
542545
-- effort, using 'genericLiftParseJSON' with your preferred 'Options':
543546
--
544547
-- @
545-
-- instance FromJSON a => FromJSON1 (Pair a) where
546-
-- liftParseJSON = 'genericLiftParseJSON' 'defaultOptions'
548+
-- customOptions = 'defaultOptions'
549+
-- { 'fieldLabelModifier' = 'map' 'Data.Char.toUpper'
550+
-- }
551+
--
552+
-- instance 'FromJSON' a => 'FromJSON1' (Pair a) where
553+
-- 'liftParseJSON' = 'genericLiftParseJSON' customOptions
547554
-- @
548555
class FromJSON1 f where
549556
liftParseJSON :: (Value -> Parser a) -> (Value -> Parser [a]) -> Value -> Parser (f a)

Data/Aeson/Types/ToJSON.hs

Lines changed: 53 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -213,18 +213,18 @@ genericLiftToEncoding opts te tel = gToEncoding opts (To1Args te tel) . from1
213213
--
214214
-- data Coord = Coord { x :: Double, y :: Double }
215215
--
216-
-- instance ToJSON Coord where
217-
-- toJSON (Coord x y) = 'object' [\"x\" '.=' x, \"y\" '.=' y]
216+
-- instance 'ToJSON' Coord where
217+
-- 'toJSON' (Coord x y) = 'object' [\"x\" '.=' x, \"y\" '.=' y]
218218
--
219-
-- toEncoding (Coord x y) = 'pairs' (\"x\" '.=' x '<>' \"y\" '.=' y)
219+
-- 'toEncoding' (Coord x y) = 'pairs' (\"x\" '.=' x '<>' \"y\" '.=' y)
220220
-- @
221221
--
222222
-- Instead of manually writing your 'ToJSON' instance, there are two options
223223
-- to do it automatically:
224224
--
225225
-- * "Data.Aeson.TH" provides Template Haskell functions which will derive an
226226
-- instance at compile time. The generated instance is optimized for your type
227-
-- so will probably be more efficient than the following two options:
227+
-- so it will probably be more efficient than the following option.
228228
--
229229
-- * The compiler can provide a default generic implementation for
230230
-- 'toJSON'.
@@ -243,8 +243,8 @@ genericLiftToEncoding opts te tel = gToEncoding opts (To1Args te tel) . from1
243243
--
244244
-- data Coord = Coord { x :: Double, y :: Double } deriving 'Generic'
245245
--
246-
-- instance ToJSON Coord where
247-
-- toEncoding = 'genericToEncoding' 'defaultOptions'
246+
-- instance 'ToJSON' Coord where
247+
-- 'toEncoding' = 'genericToEncoding' 'defaultOptions'
248248
-- @
249249
--
250250
-- Why do we provide an implementation for 'toEncoding' here? The
@@ -257,15 +257,43 @@ genericLiftToEncoding opts te tel = gToEncoding opts (To1Args te tel) . from1
257257
-- than directly emitting an 'Encoding'. Our one-liner definition of
258258
-- 'toEncoding' above bypasses the intermediate 'Value'.
259259
--
260-
-- If @DefaultSignatures@ doesn't give exactly the results you want,
260+
-- If the default implementation doesn't give exactly the results you want,
261261
-- you can customize the generic encoding with only a tiny amount of
262262
-- effort, using 'genericToJSON' and 'genericToEncoding' with your
263-
-- preferred 'Options':
263+
-- preferred 'Options'.
264+
--
265+
-- The following examples ensure that 'toEncoding' represents the same
266+
-- encoding as 'toJSON'.
267+
--
268+
-- - A typical implementation defines both 'toJSON' and 'toEncoding'
269+
-- with the same options.
270+
--
271+
-- @
272+
-- customOptions = 'defaultOptions'
273+
-- { 'fieldLabelModifier' = 'map' 'Data.Char.toUpper'
274+
-- }
275+
--
276+
-- instance 'ToJSON' Coord where
277+
-- 'toJSON' = 'genericToJSON' customOptions
278+
-- 'toEncoding' = 'genericToEncoding' customOptions
279+
-- @
280+
--
281+
-- - A minimal definition of 'ToJSON' is given by 'toJSON'.
282+
-- This is most useful to define an instance manually when
283+
-- the generic options are not satisfactory.
284+
--
285+
-- @
286+
-- instance 'ToJSON' Coord where
287+
-- 'toJSON' (Coord x y) = 'Array' (toJSON [x, y])
288+
-- @
289+
--
290+
-- - The default implementation of 'toJSON' uses 'defaultOptions'. If you leave
291+
-- 'toJSON' implicit while providing a more efficient explicit implementation
292+
-- of 'toEncoding', then it *must* be equivalent to using 'defaultOptions'.
264293
--
265294
-- @
266295
-- instance ToJSON Coord where
267-
-- toJSON = 'genericToJSON' 'defaultOptions'
268-
-- toEncoding = 'genericToEncoding' 'defaultOptions'
296+
-- 'toEncoding' = 'genericToEncoding' 'defaultOptions'
269297
-- @
270298
class ToJSON a where
271299
-- | Convert a Haskell value to a JSON-friendly intermediate type.
@@ -288,8 +316,8 @@ class ToJSON a where
288316
-- extension, and then have GHC generate a method body as follows.
289317
--
290318
-- @
291-
-- instance ToJSON Coord where
292-
-- toEncoding = 'genericToEncoding' 'defaultOptions'
319+
-- instance 'ToJSON' Coord where
320+
-- 'toEncoding' = 'genericToEncoding' 'defaultOptions'
293321
-- @
294322

295323
toEncoding :: a -> Encoding
@@ -491,7 +519,7 @@ contramapToJSONKeyFunction h x = case x of
491519
--
492520
-- * "Data.Aeson.TH" provides Template Haskell functions which will derive an
493521
-- instance at compile time. The generated instance is optimized for your type
494-
-- so will probably be more efficient than the following two options:
522+
-- so it will probably be more efficient than the following option.
495523
--
496524
-- * The compiler can provide a default generic implementation for
497525
-- 'toJSON1'.
@@ -509,19 +537,25 @@ contramapToJSONKeyFunction h x = case x of
509537
--
510538
-- data Pair = Pair { pairFst :: a, pairSnd :: b } deriving 'Generic1'
511539
--
512-
-- instance ToJSON a => ToJSON1 (Pair a)
540+
-- instance 'ToJSON' a => 'ToJSON1' (Pair a)
513541
-- @
514542
--
515-
-- If @DefaultSignatures@ doesn't give exactly the results you want,
543+
-- If the default implementation doesn't give exactly the results you want,
516544
-- you can customize the generic encoding with only a tiny amount of
517545
-- effort, using 'genericLiftToJSON' and 'genericLiftToEncoding' with
518546
-- your preferred 'Options':
519547
--
520548
-- @
521-
-- instance ToJSON a => ToJSON1 (Pair a) where
522-
-- liftToJSON = 'genericLiftToJSON' 'defaultOptions'
523-
-- liftToEncoding = 'genericLiftToEncoding' 'defaultOptions'
549+
-- customOptions = 'defaultOptions'
550+
-- { 'fieldLabelModifier' = 'map' 'Data.Char.toUpper'
551+
-- }
552+
--
553+
-- instance 'ToJSON' a => 'ToJSON1' (Pair a) where
554+
-- 'liftToJSON' = 'genericLiftToJSON' customOptions
555+
-- 'liftToEncoding' = 'genericLiftToEncoding' customOptions
524556
-- @
557+
--
558+
-- See also 'ToJSON'.
525559
class ToJSON1 f where
526560
liftToJSON :: (a -> Value) -> ([a] -> Value) -> f a -> Value
527561

@@ -588,7 +622,7 @@ toEncoding2 = liftToEncoding2 toEncoding toEncodingList toEncoding toEncodingLis
588622
-- @
589623
-- newtype F a = F [a]
590624
--
591-
-- -- This instance encodes String as an array of chars
625+
-- -- This instance encodes 'String' as an array of chars
592626
-- instance 'ToJSON1' F where
593627
-- 'liftToJSON' tj _ (F xs) = 'liftToJSON' tj ('listValue' tj) xs
594628
-- 'liftToEncoding' te _ (F xs) = 'liftToEncoding' te ('listEncoding' te) xs

0 commit comments

Comments
 (0)