on master help sign in
Merge pull request #15 from juspay/kana/omit_optional_fields
bf1e739Andrew / Kana
jrec.cabal+2−1
@@ -86,7 +86,8 @@ test-suite jrec-test
86 import: library-common
86 import: library-common
87 type: exitcode-stdio-1.0
87 type: exitcode-stdio-1.0
88 hs-source-dirs: test, src
88 hs-source-dirs: test, src
89− main-is: Spec.hs
89+ main-is: Spec.hs
90+ cpp-options: -DWITH_AESON
90 build-depends:
91 build-depends:
91 base,
92 base,
92 hspec,
93 hspec,
src/JRec/Internal.hs+11−1
@@ -631,9 +631,19 @@ class RecJsonParse (lts :: [*]) where
631instance RecJsonParse '[] where
631instance RecJsonParse '[] where
632 recJsonParse _ initSize _ = pure (ForallST (unsafeRNil initSize))
632 recJsonParse _ initSize _ = pure (ForallST (unsafeRNil initSize))
633
633
634+class FromJSON a => ParseField a where
635+ parseField :: Object -> T.Text -> Parser a
636+
637+instance FromJSON a => ParseField a where
638+ parseField = (.:)
639+
640+instance {-# OVERLAPS #-} FromJSON a => ParseField (Maybe a) where
641+ parseField = (.:?)
642+
634instance
643instance
635 ( KnownSymbol l,
644 ( KnownSymbol l,
636 FromJSON t,
645 FromJSON t,
646+ ParseField t,
637 RecJsonParse lts,
647 RecJsonParse lts,
638 RecSize lts ~ s,
648 RecSize lts ~ s,
639 KnownNat s,
649 KnownNat s,
@@ -645,7 +655,7 @@ instance
645 let lbl :: FldProxy l
655 let lbl :: FldProxy l
646 lbl = FldProxy
656 lbl = FldProxy
647 rest <- recJsonParse options initSize obj
657 rest <- recJsonParse options initSize obj
648− (v :: t) <- obj .: T.pack (fieldTransform options (symbolVal lbl))
658+ (v :: t) <- obj `parseField` T.pack (fieldTransform options (symbolVal lbl))
649 pure $ ForallST (unsafeRCons (lbl := v) =<< unForallST rest)
659 pure $ ForallST (unsafeRCons (lbl := v) =<< unForallST rest)
650
660
651-- | Machinery for NFData
661-- | Machinery for NFData
test/JRecSpec.hs+21−6
@@ -1,9 +1,10 @@
1module JRecSpec (spec) where
1module JRecSpec (spec) where
2
2
3import Control.Lens ((&), (.~), (^.))
3import Control.Lens ((&), (.~), (^.))
4+import Data.Aeson
5+import GHC.Stack
4import JRec
6import JRec
5import Test.Hspec
7import Test.Hspec
6−import GHC.Stack
7
8
8data Pair a = Pair !a !a
9data Pair a = Pair !a !a
9 deriving (Eq, Show)
10 deriving (Eq, Show)
@@ -16,10 +17,10 @@ spec = do
16 Pair (Rec (#a := 1)) (Rec (#a := 2))
17 Pair (Rec (#a := 1)) (Rec (#a := 2))
17 `shouldNotBe` Pair (Rec (#a := 2)) (Rec (#a := 2))
18 `shouldNotBe` Pair (Rec (#a := 2)) (Rec (#a := 2))
18 it "polymorphic" $ do
19 it "polymorphic" $ do
19− (Rec (#u := True, #a := 5, #b := 6, #a := 2 ) & #u .~ 5)
20+ (Rec (#u := True, #a := 5, #b := 6, #a := 2) & #u .~ 5)
20 `shouldBe` Rec (#u := 5, #a := 5, #b := 6, #a := 2)
21 `shouldBe` Rec (#u := 5, #a := 5, #b := 6, #a := 2)
21− describe "eq" $ do
22+ describe "eq" $ do
22− -- eq can compare only the first matching field, discarding the rest.
23+ -- eq can compare only the first matching field, discarding the rest.
23 it "fails if first matching field doesn't compare" $ do
24 it "fails if first matching field doesn't compare" $ do
24 Rec (#a := 1, #a := 2) `shouldNotBe` Rec (#a := 0, #a := 2)
25 Rec (#a := 1, #a := 2) `shouldNotBe` Rec (#a := 0, #a := 2)
25 it "succeeds if first matching field compares" $ do
26 it "succeeds if first matching field compares" $ do
@@ -76,8 +77,8 @@ spec = do
76 r2 = Rec (#c := 7, #a := 8)
77 r2 = Rec (#c := 7, #a := 8)
77 r1 `union` r2
78 r1 `union` r2
78 `shouldBe` Rec (#b := 5, #a := 6, #c := 7)
79 `shouldBe` Rec (#b := 5, #a := 6, #c := 7)
79− describe "insert" $ do
80+ describe "insert" $ do
80− it "simple insert" $ do
81+ it "simple insert" $ do
81 (#a := 1) `insert` Rec (#b := 2, #c := 3)
82 (#a := 1) `insert` Rec (#b := 2, #c := 3)
82 `shouldBe` Rec (#a := 1, #b := 2, #c := 3)
83 `shouldBe` Rec (#a := 1, #b := 2, #c := 3)
83 describe "insertOrSet" $ do
84 describe "insertOrSet" $ do
@@ -87,3 +88,17 @@ spec = do
87 it "overwrite" $ do
88 it "overwrite" $ do
88 insertOrSet (#c := 1) (Rec (#b := 2, #c := 3))
89 insertOrSet (#c := 1) (Rec (#b := 2, #c := 3))
89 `shouldBe` Rec (#b := 2, #c := 1)
90 `shouldBe` Rec (#b := 2, #c := 1)
91+ describe "optional fields" $ do
92+ it "encode" $ do
93+ encode (Rec (#a := (1 :: Int), #b := (Nothing :: Maybe Int)))
94+ `shouldBe` "{\"a\":1,\"b\":null}"
95+ it "encode" $ do
96+ encode (Rec (#a := (1 :: Int), #b := (Just 2 :: Maybe Int)))
97+ `shouldBe` "{\"a\":1,\"b\":2}"
98+ it "decode" $ do
99+ decode "{\"a\": 1, \"b\": null}"
100+ `shouldBe` Just (Rec (#a := (1 :: Int), #b := (Nothing :: Maybe Int)))
101+ decode "{\"a\": 1}"
102+ `shouldBe` Just (Rec (#a := (1 :: Int), #b := (Nothing :: Maybe Int)))
103+ decode "{\"a\": 1, \"b\": 2}"
104+ `shouldBe` Just (Rec (#a := (1 :: Int), #b := (Just 2 :: Maybe Int)))