on master help sign in
omit Nothing while encoding to json
commita3921134a7dc1670c31144aeb1e433544c49fa88 authorkana-sama <andrew4chrome@gmail.com> dateThu 22 Oct 2020, 18:21 (6 years ago) parentbf1e739
3 files changed+32−16
src/JRec.hs+9−8 src/JRec/Internal.hs+20−5 test/JRecSpec.hs+3−3
src/JRec.hs+9−8
@@ -10,7 +10,7 @@ module JRec
1010 append,
1111 union,
1212 insert,
13− insertOrSet
13+ insertOrSet,
1414 )
1515where
1616
@@ -63,8 +63,8 @@ append = R.combine
6363
6464-- Merges records, removing duplicates
6565--
66−-- Left-biased. Does not sort.
67−--
66+-- Left-biased. Does not sort.
67+--
6868-- O(n * m) type check complexity.
6969union ::
7070 forall lhs rhs res.
@@ -83,18 +83,19 @@ union = R.union
8383-- | Insert a field into a record that does not already contain it
8484--
8585-- O(n) type check complexity.
86−insert ::
87− forall label value lts res.
86+insert ::
87+ forall label value lts res.
8888 ( KnownNat (1 + R.RecSize lts),
8989 KnownNat (R.RecSize lts),
9090 KnownSymbol label,
9191 R.RecCopy lts lts res,
9292 res ~ ((label := value) : lts),
9393 R.RemoveAccessTo label lts ~ lts
94− ) =>
94+ ) =>
9595 label := value ->
96− Rec lts -> Rec res
97−insert = R.combine . Rec
96+ Rec lts ->
97+ Rec res
98+insert = R.combine . Rec
9899
99100-- | Insert a field into a record. Set it if it already exists
100101--
src/JRec/Internal.hs+20−5
@@ -32,6 +32,7 @@ import qualified Control.Monad.State as S
3232import Data.Aeson
3333import Data.Aeson.Types (Parser)
3434import Data.Constraint
35+import Data.Maybe (catMaybes)
3536import Data.Proxy
3637import qualified Data.Text as T
3738import Data.Typeable
@@ -115,7 +116,7 @@ instance RecEq lts lts => Eq (Rec lts) where
115116
116117#ifdef WITH_AESON
117118instance
118− ( RecApply lts lts ToJSON
119+ ( RecApply lts lts EncodeField
119120 ) =>
120121 ToJSON (Rec lts)
121122 where
@@ -124,6 +125,7 @@ instance
124125
125126instance (RecSize lts ~ s, KnownNat s, RecJsonParse lts) => FromJSON (Rec lts) where
126127 parseJSON = recJsonParser defaultJSONOptions
128+
127129#endif
128130
129131instance RecNfData lts lts => NFData (Rec lts) where
@@ -552,13 +554,26 @@ reflectRecFold _ f r =
552554showRec :: forall lts. (RecApply lts lts Show) => Rec lts -> [(String, String)]
553555showRec = reflectRec @Show Proxy (\k v -> (k, show v))
554556
555−recToValue :: forall lts. (RecApply lts lts ToJSON) => JSONOptions -> Rec lts -> Value
557+class ToJSON a => EncodeField a where
558+ encodeField :: a -> Maybe Value
559+ encodeKV :: T.Text -> a -> Series
560+
561+instance ToJSON a => EncodeField a where
562+ encodeField = pure . toJSON
563+ encodeKV = (.=)
564+
565+instance {-# OVERLAPS #-} ToJSON a => EncodeField (Maybe a) where
566+ encodeField = fmap toJSON
567+ encodeKV _ Nothing = mempty
568+ encodeKV k v = k .= v
569+
570+recToValue :: forall lts. (RecApply lts lts EncodeField) => JSONOptions -> Rec lts -> Value
556571recToValue options r =
557− object $ reflectRec @ToJSON Proxy (\k v -> (T.pack (fieldTransform options k), toJSON v)) r
572+ object $ catMaybes $ reflectRec @EncodeField Proxy (\k v -> (T.pack (fieldTransform options k),) <$> encodeField v) r
558573
559−recToEncoding :: forall lts. (RecApply lts lts ToJSON) => JSONOptions -> Rec lts -> Encoding
574+recToEncoding :: forall lts. (RecApply lts lts EncodeField) => JSONOptions -> Rec lts -> Encoding
560575recToEncoding options r =
561− pairs $ mconcat $ reflectRec @ToJSON Proxy (\k v -> (T.pack (fieldTransform options k) .= v)) r
576+ pairs $ mconcat $ reflectRec @EncodeField Proxy (\k v -> (T.pack (fieldTransform options k) `encodeKV` v)) r
562577
563578recJsonParser ::
564579 forall lts s.
test/JRecSpec.hs+3−3
@@ -91,14 +91,14 @@ spec = do
9191 describe "optional fields" $ do
9292 it "encode" $ do
9393 encode (Rec (#a := (1 :: Int), #b := (Nothing :: Maybe Int)))
94− `shouldBe` "{\"a\":1,\"b\":null}"
94+ `shouldBe` "{\"a\":1}"
9595 it "encode" $ do
9696 encode (Rec (#a := (1 :: Int), #b := (Just 2 :: Maybe Int)))
9797 `shouldBe` "{\"a\":1,\"b\":2}"
9898 it "decode" $ do
99− decode "{\"a\": 1, \"b\": null}"
100− `shouldBe` Just (Rec (#a := (1 :: Int), #b := (Nothing :: Maybe Int)))
10199 decode "{\"a\": 1}"
102100 `shouldBe` Just (Rec (#a := (1 :: Int), #b := (Nothing :: Maybe Int)))
101+ decode "{\"a\": 1, \"b\": null}"
102+ `shouldBe` Just (Rec (#a := (1 :: Int), #b := (Nothing :: Maybe Int)))
103103 decode "{\"a\": 1, \"b\": 2}"
104104 `shouldBe` Just (Rec (#a := (1 :: Int), #b := (Just 2 :: Maybe Int)))