on master help sign in
Add docs for FromJSONKey
commit2435d88a1e40043f4b3d0a27053a1da534a46378 authorAndrew Martin <amartin@layer3com.com> dateMon 13 Jun 2016, 09:57 (10 years ago) parentf81a260
2 files changed+35−13
Data/Aeson/Types/FromJSON.hs+32−10 Data/Aeson/Types/ToJSON.hs+3−3
Data/Aeson/Types/FromJSON.hs+32−10
@@ -321,20 +321,33 @@ class FromJSON a where
321321-- Classes and types for map keys
322322-------------------------------------------------------------------------------
323323
324+-- | Read the docs for 'ToJSONKey' first. This class is a conversion
325+-- in the opposite direction. If you have a newtype wrapper around 'Text',
326+-- the recommended way to define instances is with generalized newtype deriving:
327+--
328+-- > newtype SomeId = SomeId { getSomeId :: Text }
329+-- > deriving (Eq,Ord,Hashable,FromJSONKey)
330+--
324331class FromJSONKey a where
332+ -- | Strategy for parsing the key of a map-like container.
325333 fromJSONKey :: FromJSONKeyFunction a
326334 default fromJSONKey :: FromJSON a => FromJSONKeyFunction a
327335 fromJSONKey = FromJSONKeyValue parseJSON
336+ -- | This is similar in spirit to the 'readList' method of 'Read'.
337+ -- It makes it possible to give 'String' keys special treatment
338+ -- without using @OverlappingInstances@. End users should always
339+ -- be able to use the default implementation of this method.
328340 fromJSONKeyList :: FromJSONKeyFunction [a]
329341 default fromJSONKeyList :: FromJSON a => FromJSONKeyFunction [a]
330342 fromJSONKeyList = FromJSONKeyValue parseJSON
331343
332−-- | With GHC 7.8 + we carry around 'Coercible Text a' dictionary,
333−-- to have even some amount of safety net.
334−-- Unfortunately we cannot enforce that 'Hashable' instance agree on the type level
344+-- | With GHC 7.8+ we carry around @'Coercible' 'Text' a@ dictionary,
345+-- to give us an assurance that the program will not segfault.
346+-- Unfortunately we cannot enforce that the 'Eq' instances or the
347+-- 'Hashable' instances for 'Text' and @a@ agree.
335348--
336−-- ATM this type is intentionally not exported. FromJSONKeyFunction can be inspected,
337−-- but cannot be constructed.
349+-- At the moment this type is intentionally not exported. 'FromJSONKeyFunction'
350+-- can be inspected, but cannot be constructed.
338351data CoerceText a where
339352#if HAS_COERCIBLE
340353 CoerceText :: Coercible Text a => CoerceText a
@@ -342,12 +355,19 @@ data CoerceText a where
342355 CoerceText :: CoerceText a
343356#endif
344357
358+-- | This type is related to 'ToJSONKeyFunction'. If 'FromJSONKeyValue' is used in the
359+-- 'FromJSONKey' instance, then 'ToJSONKeyValue' should be used in the 'ToJSONKey'
360+-- instance. The other three data constructors for this type all correspond to
361+-- 'ToJSONKeyText'. Strictly speaking, 'FromJSONKeyTextParser' is more powerful than
362+-- 'FromJSONKeyText', which is in turn more powerful than 'FromJSONKeyCoerce'.
363+-- For performance reasons, these exist as three options instead of one.
345364data FromJSONKeyFunction a
346− = FromJSONKeyCoerce (CoerceText a)
347− | FromJSONKeyText (Text -> a)
348− | FromJSONKeyTextParser (Text -> Parser a)
349− | FromJSONKeyValue (Value -> Parser a)
365+ = FromJSONKeyCoerce (CoerceText a) -- ^ uses 'coerce' ('unsafeCoerce' in older GHCs)
366+ | FromJSONKeyText (Text -> a) -- ^ conversion from 'Text' that always succeeds
367+ | FromJSONKeyTextParser (Text -> Parser a) -- ^ conversion from 'Text' that may fail
368+ | FromJSONKeyValue (Value -> Parser a) -- ^ conversion for non-textual keys
350369
370+-- | Only law abiding up to interpretation
351371instance Functor FromJSONKeyFunction where
352372 fmap h (FromJSONKeyCoerce CoerceText) = FromJSONKeyText (h . coerce')
353373 fmap h (FromJSONKeyText f) = FromJSONKeyText (h . f)
@@ -356,7 +376,9 @@ instance Functor FromJSONKeyFunction where
356376
357377-- | Construct 'FromJSONKeyFunction' for types coercible from 'Text'. This
358378-- conversion is still unsafe, as 'Hashable' and 'Eq' instances of @a@ should be
359−-- compatible with 'Text' i.e. hash values be equal for wrapped values as well.
379+-- compatible with 'Text' i.e. hash values should be equal for wrapped values as well.
380+-- This property will always be maintained if the 'Hashable' and 'Eq' instances
381+-- are derived with generalized newtype deriving.
360382fromJSONKeyCoerce ::
361383#if HAS_COERCIBLE
362384 Coercible Text a =>
Data/Aeson/Types/ToJSON.hs+3−3
@@ -414,14 +414,14 @@ instance KeyValue Pair where
414414-- maximize performance.
415415
416416class ToJSONKey a where
417− -- | Provides a way to use a data type as the key for a map-like
418− -- container.
417+ -- | Strategy for rendering the key for a map-like container.
419418 toJSONKey :: ToJSONKeyFunction a
420419 default toJSONKey :: ToJSON a => ToJSONKeyFunction a
421420 toJSONKey = ToJSONKeyValue (toJSON, toEncoding)
422421 -- | This is similar in spirit to the 'showsList' method of 'Show'.
423422 -- It makes it possible to give 'String' keys special treatment
424− -- without using @OverlappingInstances@.
423+ -- without using @OverlappingInstances@. End users should always
424+ -- be able to use the default implementation of this method.
425425 toJSONKeyList :: ToJSONKeyFunction [a]
426426 default toJSONKeyList :: ToJSON a => ToJSONKeyFunction [a]
427427 toJSONKeyList = ToJSONKeyValue (toJSON, toEncoding)