Skip to content

Commit fa2cbbb

Browse files
authored
Merge pull request #38 from foresttoney/master
Add assocOptional and encodeOptional encode combinators
2 parents cecdcbd + be86b42 commit fa2cbbb

File tree

4 files changed

+54
-8
lines changed

4 files changed

+54
-8
lines changed

bower.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
"dependencies": {
2525
"purescript-argonaut-core": "^3.0.0",
2626
"purescript-generics": "^4.0.0",
27-
"purescript-integers": "^3.0.0"
27+
"purescript-integers": "^3.0.0",
28+
"purescript-maybe": "^3.0.0"
2829
},
2930
"devDependencies": {
3031
"purescript-strongcheck": "^3.1.0"

src/Data/Argonaut/Encode.purs

+10-1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,13 @@ module Data.Argonaut.Encode
44
) where
55

66
import Data.Argonaut.Encode.Class (class EncodeJson, encodeJson)
7-
import Data.Argonaut.Encode.Combinators (assoc, extend, (:=), (~>))
7+
import Data.Argonaut.Encode.Combinators
8+
( assoc
9+
, assocOptional
10+
, extend
11+
, extendOptional
12+
, (:=)
13+
, (:=?)
14+
, (~>)
15+
, (~>?)
16+
)

src/Data/Argonaut/Encode/Combinators.purs

+19-2
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,17 @@
33
-- | ``` purescript
44
-- | myJson
55
-- | = "key1" := value1
6-
-- | ~> "key2" := value2
7-
-- | ~> jsonEmptyObject
6+
-- | ~> "key2" :=? value2
7+
-- | ~>? "key3" := value3
8+
-- | ~> jsonEmptyOibject
89
-- | ```
910
module Data.Argonaut.Encode.Combinators where
1011

1112
import Prelude
1213

1314
import Data.Argonaut.Core (Json, JAssoc, foldJsonObject, fromObject, jsonSingletonObject)
1415
import Data.Argonaut.Encode.Class (class EncodeJson, encodeJson)
16+
import Data.Maybe (Maybe(..))
1517
import Data.StrMap as SM
1618
import Data.Tuple (Tuple(..))
1719

@@ -22,6 +24,13 @@ infix 7 assoc as :=
2224
assoc :: forall a. EncodeJson a => String -> a -> JAssoc
2325
assoc k = Tuple k <<< encodeJson
2426

27+
-- | Creates an optional `JAssoc` entry, representing an optional key/value pair for an object.
28+
infix 7 assocOptional as :=?
29+
30+
-- | The named implementation of the `(:=?)` operator.
31+
assocOptional :: forall a. EncodeJson a => String -> Maybe a -> Maybe JAssoc
32+
assocOptional k = (<$>) (((:=) k) <<< encodeJson)
33+
2534
-- | Extends a Json object with a `JAssoc` property.
2635
infixr 6 extend as ~>
2736

@@ -32,3 +41,11 @@ extend (Tuple k v) =
3241
(jsonSingletonObject k v)
3342
(SM.insert k v >>> fromObject)
3443
<<< encodeJson
44+
45+
-- | Optionally extends a Json object with an optional `JAssoc` property.
46+
infixr 6 extendOptional as ~>?
47+
48+
-- | The named implementation of the `(~>?)` operator.
49+
extendOptional :: forall a. EncodeJson a => Maybe JAssoc -> a -> Json
50+
extendOptional (Just kv) = (~>) kv
51+
extendOptional Nothing = encodeJson

test/Test/Main.purs

+23-4
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,15 @@ module Test.Main where
33
import Prelude
44

55
import Control.Monad.Eff.Console (log)
6-
76
import Data.Argonaut.Core (JObject, Json, isObject, toObject)
87
import Data.Argonaut.Decode (decodeJson)
9-
import Data.Argonaut.Encode (encodeJson, (:=), (~>))
8+
import Data.Argonaut.Encode (class EncodeJson, encodeJson, (:=), (:=?), (~>), (~>?))
109
import Data.Argonaut.Gen (genJson)
1110
import Data.Either (Either(..))
1211
import Data.Foldable (foldl)
13-
import Data.Maybe (Maybe(..), maybe, isJust)
12+
import Data.Maybe (Maybe(..), isJust, isNothing, maybe)
1413
import Data.StrMap as SM
1514
import Data.Tuple (Tuple(..))
16-
1715
import Test.StrongCheck (SC, quickCheck, quickCheck', (<?>))
1816
import Test.StrongCheck.Arbitrary (class Arbitrary)
1917
import Test.StrongCheck.Gen (suchThat, resize)
@@ -26,6 +24,9 @@ main = do
2624

2725
newtype TestJson = TestJson Json
2826

27+
instance encodeJsonTestJson :: EncodeJson TestJson where
28+
encodeJson (TestJson x) = encodeJson x
29+
2930
instance arbitraryTestJson :: Arbitrary TestJson where
3031
arbitrary = TestJson <$> (resize 5 genJson)
3132

@@ -59,8 +60,12 @@ combinatorsCheck :: SC () Unit
5960
combinatorsCheck = do
6061
log "Check assoc builder `:=`"
6162
quickCheck' 20 prop_assoc_builder_str
63+
log "Check assocOptional builder `:=?`"
64+
quickCheck' 20 prop_assoc_optional_builder_str
6265
log "Check JAssoc append `~>`"
6366
quickCheck' 20 prop_assoc_append
67+
log "Check JAssoc appendOptional `~>?`"
68+
quickCheck' 20 prop_assoc_append_optional
6469
log "Check get field `obj .? 'foo'`"
6570
quickCheck' 20 prop_get_jobject_field
6671

@@ -72,13 +77,27 @@ combinatorsCheck = do
7277
Tuple k json ->
7378
(key == k) && (decodeJson json == Right str)
7479

80+
prop_assoc_optional_builder_str :: Tuple String (Maybe String) -> Boolean
81+
prop_assoc_optional_builder_str (Tuple key maybeStr) =
82+
case (key :=? maybeStr) of
83+
Just (Tuple k json) ->
84+
(key == k) && (decodeJson json == Right maybeStr)
85+
Nothing -> true
86+
7587
prop_assoc_append :: (Tuple (Tuple String TestJson) Obj) -> Boolean
7688
prop_assoc_append (Tuple (Tuple key (TestJson val)) (Obj obj)) =
7789
let appended = (key := val) ~> obj
7890
in case toObject appended >>= SM.lookup key of
7991
Just value -> true
8092
_ -> false
8193

94+
prop_assoc_append_optional :: Tuple (Tuple String (Maybe TestJson)) Obj -> Boolean
95+
prop_assoc_append_optional (Tuple (Tuple key maybeVal) (Obj obj)) =
96+
let appended = (key :=? maybeVal) ~>? obj
97+
in case toObject appended >>= SM.lookup key of
98+
Just value -> isJust maybeVal
99+
_ -> isNothing maybeVal
100+
82101
prop_get_jobject_field :: Obj -> Boolean
83102
prop_get_jobject_field (Obj obj) =
84103
maybe false go $ toObject obj

0 commit comments

Comments
 (0)