11module Data.Argonaut.Decode.Combinators
22 ( getField
3+ , getFieldDeprecated
34 , getFieldOptional
5+ , getFieldOptionalDeprecated
6+ , getFieldOptional'
47 , defaultField
8+ , defaultFieldDeprecated
9+ , (.:)
510 , (.?)
11+ , (.:!)
12+ , (.:?)
613 , (.??)
14+ , (.!=)
715 , (.?=)
816 ) where
917
1018import Prelude
1119
12- import Data.Argonaut.Core (Json )
20+ import Data.Argonaut.Core (Json , isNull )
1321import Data.Argonaut.Decode.Class (class DecodeJson , decodeJson )
1422import Data.Bifunctor (lmap )
1523import Data.Either (Either (..))
1624import Data.Maybe (Maybe (..), fromMaybe , maybe )
1725import Foreign.Object as FO
26+ import Prim.TypeError (class Warn , Text )
1827
28+ -- | Attempt to get the value for a given key on an `Object Json`.
29+ -- |
30+ -- | Use this accessor if the key and value *must* be present in your object.
31+ -- | If the key and value are optional, use `getFieldOptional'` (`.:?`) instead.
1932getField :: forall a . DecodeJson a => FO.Object Json -> String -> Either String a
2033getField o s =
2134 maybe
2235 (Left $ " Expected field " <> show s)
2336 (elaborateFailure s <<< decodeJson)
2437 (FO .lookup s o)
2538
26- infix 7 getField as .?
39+ infix 7 getField as .:
2740
41+ getFieldDeprecated
42+ :: forall a . Warn ( Text " `.?` is deprecated, use `.:` instead" )
43+ => DecodeJson a
44+ => FO.Object Json
45+ -> String
46+ -> Either String a
47+ getFieldDeprecated = getField
48+
49+ infix 7 getFieldDeprecated as .?
50+
51+ -- | Attempt to get the value for a given key on an `Object Json`.
52+ -- |
53+ -- | The result will be `Right Nothing` if the key and value are not present,
54+ -- | or if the key is present and the value is `null`.
55+ -- |
56+ -- | Use this accessor if the key and value are optional in your object.
57+ -- | If the key and value are mandatory, use `getField` (`.:`) instead.
58+ getFieldOptional' :: forall a . DecodeJson a => FO.Object Json -> String -> Either String (Maybe a )
59+ getFieldOptional' o s =
60+ maybe
61+ (pure Nothing )
62+ decode
63+ (FO .lookup s o)
64+ where
65+ decode json =
66+ if isNull json
67+ then pure Nothing
68+ else Just <$> decodeJson json
69+
70+ infix 7 getFieldOptional' as .:?
71+
72+ -- | Attempt to get the value for a given key on an `Object Json`.
73+ -- |
74+ -- | The result will be `Right Nothing` if the key and value are not present,
75+ -- | but will fail if the key is present but the value cannot be converted to the right type.
76+ -- |
77+ -- | This function will treat `null` as a value and attempt to decode it into your desired type.
78+ -- | If you would like to treat `null` values the same as absent values, use
79+ -- | `getFieldOptional` (`.:?`) instead.
2880getFieldOptional :: forall a . DecodeJson a => FO.Object Json -> String -> Either String (Maybe a )
2981getFieldOptional o s =
3082 maybe
@@ -34,12 +86,48 @@ getFieldOptional o s =
3486 where
3587 decode json = Just <$> (elaborateFailure s <<< decodeJson) json
3688
37- infix 7 getFieldOptional as .??
89+ infix 7 getFieldOptional as .:!
90+
91+ getFieldOptionalDeprecated
92+ :: forall a . Warn ( Text " `.??` is deprecated, use `.:!` or `.:?` instead" )
93+ => DecodeJson a
94+ => FO.Object Json
95+ -> String
96+ -> Either String (Maybe a )
97+ getFieldOptionalDeprecated = getFieldOptional
3898
99+ infix 7 getFieldOptionalDeprecated as .??
100+
101+ -- | Helper for use in combination with `.:?` to provide default values for optional
102+ -- | `Object Json` fields.
103+ -- |
104+ -- | Example usage:
105+ -- | ```purescript
106+ -- | newtype MyType = MyType
107+ -- | { foo :: String
108+ -- | , bar :: Maybe Int
109+ -- | , baz :: Boolean
110+ -- | }
111+ -- |
112+ -- | instance decodeJsonMyType :: DecodeJson MyType where
113+ -- | decodeJson json = do
114+ -- | x <- decodeJson json
115+ -- | foo <- x .: "foo" -- mandatory field
116+ -- | bar <- x .:? "bar" -- optional field
117+ -- | baz <- x .:? "baz" .!= false -- optional field with default value of `false`
118+ -- | pure $ MyType { foo, bar, baz }
119+ -- | ```
39120defaultField :: forall a . Either String (Maybe a ) -> a -> Either String a
40121defaultField parser default = fromMaybe default <$> parser
41122
42- infix 6 defaultField as .?=
123+ infix 6 defaultField as .!=
124+
125+ defaultFieldDeprecated
126+ :: forall a . Warn ( Text " `.?=` is deprecated, use `.!=` instead" )
127+ => Either String (Maybe a ) -> a -> Either String a
128+ defaultFieldDeprecated = defaultField
129+
130+ infix 6 defaultFieldDeprecated as .?=
43131
44132elaborateFailure :: ∀ a . String -> Either String a -> Either String a
45133elaborateFailure s e =
0 commit comments