Skip to content

Commit 56d4522

Browse files
committed
Added encode/decode instances for NonEmpty Array and NonEmpty List.
1 parent 0e33061 commit 56d4522

File tree

3 files changed

+41
-10
lines changed

3 files changed

+41
-10
lines changed

src/Data/Argonaut/Decode/Class.purs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ module Data.Argonaut.Decode.Class
66
) where
77

88
import Prelude
9-
9+
import Data.Array as Arr
10+
import Data.Map as M
11+
import Data.StrMap as SM
12+
import Control.Alternative (class Plus)
1013
import Data.Argonaut.Core (Json, JArray, JObject, isNull, foldJsonNull, foldJsonBoolean, foldJsonNumber, foldJsonString, toArray, toNumber, toObject, toString, toBoolean)
1114
import Data.Array (zipWithA)
1215
import Data.Bifunctor (lmap)
@@ -15,13 +18,12 @@ import Data.Foldable (find)
1518
import Data.Generic (class Generic, GenericSpine(..), GenericSignature(..), fromSpine, toSignature)
1619
import Data.Int (fromNumber)
1720
import Data.List (List(..), (:), fromFoldable)
18-
import Data.Map as M
21+
import Data.List as L
1922
import Data.Maybe (maybe, Maybe(..))
23+
import Data.NonEmpty (NonEmpty, singleton, (:|))
2024
import Data.String (charAt, toChar)
21-
import Data.StrMap as SM
2225
import Data.Traversable (traverse, for)
2326
import Data.Tuple (Tuple(..))
24-
2527
import Type.Proxy (Proxy(..))
2628

2729
class DecodeJson a where
@@ -110,6 +112,23 @@ instance decodeJsonString :: DecodeJson String where
110112
instance decodeJsonJson :: DecodeJson Json where
111113
decodeJson = Right
112114

115+
116+
toNonEmpty :: forall a f. (Plus f) => ({ head :: f a -> Maybe a, tail :: f a -> Maybe (f a) }) -> (f a) -> Either String (NonEmpty f a)
117+
toNonEmpty i a = case (Tuple (i.head a) (i.tail a)) of
118+
(Tuple Nothing _) -> Left "is empty."
119+
(Tuple (Just h) Nothing) -> Right $ singleton h
120+
(Tuple (Just h) (Just t)) -> Right $ h :| t
121+
122+
instance decodeJsonNonEmptyArray :: (DecodeJson a) => DecodeJson (NonEmpty Array a) where
123+
decodeJson
124+
= lmap ("Couldn't decode Array: " <> _)
125+
<<< (traverse decodeJson <=< (toNonEmpty { head : Arr.head, tail : Arr.tail } ) <=< decodeJArray)
126+
127+
instance decodeJsonNonEmptyList :: (DecodeJson a) => DecodeJson (NonEmpty List a) where
128+
decodeJson
129+
= lmap ("Couldn't decode NonEmpty List: " <> _)
130+
<<< (traverse decodeJson <=< (lmap ("List" <> _) <<< toNonEmpty { head : L.head, tail : L.tail }) <=< map (map fromFoldable) decodeJArray)
131+
113132
instance decodeJsonChar :: DecodeJson Char where
114133
decodeJson j =
115134
maybe (Left $ "Expected character but found: " <> show j) Right

src/Data/Argonaut/Encode/Class.purs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
module Data.Argonaut.Encode.Class where
22

33
import Prelude
4-
54
import Data.Argonaut.Core (Json(), jsonNull, fromBoolean, fromNumber, fromString, fromArray, fromObject)
65
import Data.Either (Either(), either)
6+
import Data.Array as Arr
77
import Data.Foldable (foldr)
88
import Data.Generic (class Generic, GenericSpine(..), toSpine)
99
import Data.Int (toNumber)
1010
import Data.List (List(..), (:), toUnfoldable)
1111
import Data.Map as M
1212
import Data.Maybe (Maybe(..))
13+
import Data.NonEmpty (NonEmpty(..))
1314
import Data.String (singleton)
1415
import Data.StrMap as SM
1516
import Data.Tuple (Tuple(..))
@@ -74,6 +75,12 @@ instance encodeJsonJString :: EncodeJson String where
7475
instance encodeJsonJson :: EncodeJson Json where
7576
encodeJson = id
7677

78+
instance encodeJsonNonEmptyArray :: (EncodeJson a) => EncodeJson (NonEmpty Array a) where
79+
encodeJson (NonEmpty h t) = encodeJson $ Arr.cons h t
80+
81+
instance encodeJsonNonEmptyList :: (EncodeJson a) => EncodeJson (NonEmpty List a) where
82+
encodeJson (NonEmpty h t) = encodeJson $ Arr.cons h (toUnfoldable t)
83+
7784
instance encodeJsonChar :: EncodeJson Char where
7885
encodeJson = encodeJson <<< singleton
7986

test/Test/Main.purs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
module Test.Main where
22

33
import Prelude
4-
4+
import Data.StrMap as SM
55
import Control.Monad.Eff.Console (log, logShow)
6-
76
import Data.Argonaut.Core (JObject, Json, toObject, fromObject, fromArray, fromString, fromNumber, fromBoolean, jsonNull)
87
import Data.Argonaut.Decode (decodeJson)
98
import Data.Argonaut.Encode (encodeJson, gEncodeJson, (:=), (~>))
@@ -12,11 +11,11 @@ import Data.Either (Either(..))
1211
import Data.Foldable (foldl)
1312
import Data.Function (on)
1413
import Data.Generic (class Generic)
15-
import Data.List (fromFoldable)
14+
import Data.List (List, fromFoldable, singleton)
15+
import Data.List as L
1616
import Data.Maybe (Maybe(..), maybe, isJust)
17-
import Data.StrMap as SM
17+
import Data.NonEmpty (NonEmpty(..), (:|))
1818
import Data.Tuple (Tuple(..), fst)
19-
2019
import Test.StrongCheck (SC, quickCheck, quickCheck', (<?>))
2120
import Test.StrongCheck.Arbitrary (class Arbitrary, arbitrary)
2221
import Test.StrongCheck.Data.AlphaNumString (AlphaNumString(..))
@@ -144,6 +143,8 @@ data User
144143
{ name :: String
145144
, bio :: Maybe String
146145
, age :: Int
146+
, hobbies :: NonEmpty Array String
147+
, accesslog :: NonEmpty List String
147148
, balance :: Number
148149
, banned :: Boolean
149150
, tweets :: Array String
@@ -170,13 +171,17 @@ genericsCheck = do
170171
, balance: 26.6
171172
, banned: false
172173
, tweets: ["Hello", "What's up"]
174+
, hobbies: "Jump Rope" :| ["Sightseeing"]
175+
, accesslog: "223.67.92.1" :| L.singleton "210.5.2.25"
173176
, followers:
174177
[ Anonymous
175178
, Guest "someGuest"
176179
, Registered
177180
{ name: "user2"
178181
, bio: Nothing
179182
, age: 6
183+
, hobbies: "Jump Rope" :| ["Cooking"]
184+
, accesslog: "152.67.25.1" :| L.singleton "210.5.2.25"
180185
, balance: 32.1
181186
, banned: false
182187
, tweets: ["Hi"]

0 commit comments

Comments
 (0)