git.iko.soy/rowtype-yoga/purescript-yoga-json
on main help sign in
Postel's law for NonEmpty* (#18)
ccbde17Mark Eibes
src/Yoga/JSON.purs+11−4
@@ -36,6 +36,7 @@ import Control.Comonad.Cofree as Cofree
36import Control.Monad.Except (ExceptT(..), except, runExcept, throwError, withExcept)
36import Control.Monad.Except (ExceptT(..), except, runExcept, throwError, withExcept)
37import Data.Array as Array
37import Data.Array as Array
38import Data.Array.NonEmpty (NonEmptyArray, fromArray, toArray)
38import Data.Array.NonEmpty (NonEmptyArray, fromArray, toArray)
39+import Data.Array.NonEmpty as NonEmptyArray
39import Data.Bifunctor (lmap)
40import Data.Bifunctor (lmap)
40import Data.DateTime (DateTime)
41import Data.DateTime (DateTime)
41import Data.DateTime.Instant (Instant, instant, unInstant)
42import Data.DateTime.Instant (Instant, instant, unInstant)
@@ -54,10 +55,10 @@ import Data.Maybe (Maybe(..), fromMaybe, fromMaybe', maybe)
54import Data.Newtype (class Newtype, unwrap, wrap)
55import Data.Newtype (class Newtype, unwrap, wrap)
55import Data.Nullable (Nullable, toMaybe, toNullable)
56import Data.Nullable (Nullable, toMaybe, toNullable)
56import Data.Number as Number
57import Data.Number as Number
57−import Data.String.NonEmpty.Internal (NonEmptyString)
58+import Data.String.NonEmpty (NonEmptyString)
58−import Data.String.NonEmpty.Internal as NonEmptyString
59+import Data.String.NonEmpty as NonEmptyString
59import Data.Symbol (class IsSymbol, reflectSymbol)
60import Data.Symbol (class IsSymbol, reflectSymbol)
60−import Data.Time.Duration (Days(..), Hours(..), Milliseconds(..), Minutes(..), Seconds(..))
61+import Data.Time.Duration (Days, Hours, Milliseconds, Minutes, Seconds)
61import Data.Traversable (traverse)
62import Data.Traversable (traverse)
62import Data.Tuple (Tuple(..))
63import Data.Tuple (Tuple(..))
63import Data.Variant (Variant, inj, on)
64import Data.Variant (Variant, inj, on)
@@ -228,7 +229,13 @@ instance ReadForeign Boolean where
228instance ReadForeign a ⇒ ReadForeign (Array a) where
229instance ReadForeign a ⇒ ReadForeign (Array a) where
229 readImpl = sequenceCombining <<< mapWithIndex readAtIdx <=< readArray
230 readImpl = sequenceCombining <<< mapWithIndex readAtIdx <=< readArray
230
231
232+instance ReadForeign (Maybe (NonEmptyString)) where
233+ readImpl = readImpl >=> pure <<< NonEmptyString.fromString
234+
235+else instance ReadForeign a ⇒ ReadForeign (Maybe (NonEmptyArray a)) where
236+ readImpl = readImpl >=> pure <<< NonEmptyArray.fromArray
237+
231−instance ReadForeign a ⇒ ReadForeign (Maybe a) where
238+else instance ReadForeign a ⇒ ReadForeign (Maybe a) where
232 readImpl = readNullOrUndefined readImpl
239 readImpl = readNullOrUndefined readImpl
233 where
240 where
234 readNullOrUndefined _ value | isNull value || isUndefined value = pure
241 readNullOrUndefined _ value | isNull value || isUndefined value = pure
test/BasicsSpec.purs+6
@@ -2,6 +2,7 @@ module Test.BasicsSpec where
2
2
3import Prelude
3import Prelude
4
4
5+import Data.Array.NonEmpty (NonEmptyArray)
5import Data.Array.NonEmpty as NEA
6import Data.Array.NonEmpty as NEA
6import Data.Either (Either(..))
7import Data.Either (Either(..))
7import Data.Foldable (traverse_)
8import Data.Foldable (traverse_)
@@ -59,6 +60,8 @@ spec = describe "En- and decoding" $ do
59 it "roundtrips LazyList" $ traverse_ roundtrips (LazyList.fromFoldable [ [ "A", "B" ], [] ])
60 it "roundtrips LazyList" $ traverse_ roundtrips (LazyList.fromFoldable [ [ "A", "B" ], [] ])
60 it "roundtrips List" $ traverse_ roundtrips (List.fromFoldable [ [ "A", "B" ], [] ])
61 it "roundtrips List" $ traverse_ roundtrips (List.fromFoldable [ [ "A", "B" ], [] ])
61 it "roundtrips NonEmptyArray" $ roundtrips (NEA.cons' "A" [ "B" ])
62 it "roundtrips NonEmptyArray" $ roundtrips (NEA.cons' "A" [ "B" ])
63+ it "decodes Maybe NonEmptyArray" $
64+ readJSON "[]" `shouldEqual` Right (Nothing ∷ _ (NonEmptyArray Int))
62 it "roundtrips Object" $ roundtrips (Object.fromHomogeneous { a: 12, b: 54 })
65 it "roundtrips Object" $ roundtrips (Object.fromHomogeneous { a: 12, b: 54 })
63 it "roundtrips String Map" $ roundtrips (Map.fromFoldable [ ("A" /\ 8), ("C" /\ 7) ])
66 it "roundtrips String Map" $ roundtrips (Map.fromFoldable [ ("A" /\ 8), ("C" /\ 7) ])
64 it "roundtrips Int Map" $ roundtrips (Map.fromFoldable [ (4 /\ "B"), (8 /\ "D") ])
67 it "roundtrips Int Map" $ roundtrips (Map.fromFoldable [ (4 /\ "B"), (8 /\ "D") ])
@@ -172,6 +175,9 @@ spec = describe "En- and decoding" $ do
172 it "fails to decode empty strings" do
175 it "fails to decode empty strings" do
173 let (result ∷ (Either _ NonEmptyString)) = readJSON (show "")
176 let (result ∷ (Either _ NonEmptyString)) = readJSON (show "")
174 result `shouldEqual` Left (pure $ ForeignError "String must not be empty")
177 result `shouldEqual` Left (pure $ ForeignError "String must not be empty")
178+ it "succeeds decoding optional empty strings" do
179+ let (result ∷ (Either _ (Maybe NonEmptyString))) = readJSON (show "")
180+ result `shouldEqual` Right Nothing
175
181
176 describe "works on trees" do
182 describe "works on trees" do
177 it "roundtrips" do
183 it "roundtrips" do