on master help sign in
omit Nothing while encoding to json
a392113kana-sama
src/JRec.hs+9−8
@@ -10,7 +10,7 @@ module JRec
10 append,
10 append,
11 union,
11 union,
12 insert,
12 insert,
13− insertOrSet
13+ insertOrSet,
14 )
14 )
15where
15where
16
16
@@ -63,8 +63,8 @@ append = R.combine
63
63
64-- Merges records, removing duplicates
64-- Merges records, removing duplicates
65--
65--
66−-- Left-biased. Does not sort.
66+-- Left-biased. Does not sort.
67−--
67+--
68-- O(n * m) type check complexity.
68-- O(n * m) type check complexity.
69union ::
69union ::
70 forall lhs rhs res.
70 forall lhs rhs res.
@@ -83,18 +83,19 @@ union = R.union
83-- | Insert a field into a record that does not already contain it
83-- | Insert a field into a record that does not already contain it
84--
84--
85-- O(n) type check complexity.
85-- O(n) type check complexity.
86−insert ::
86+insert ::
87− forall label value lts res.
87+ forall label value lts res.
88 ( KnownNat (1 + R.RecSize lts),
88 ( KnownNat (1 + R.RecSize lts),
89 KnownNat (R.RecSize lts),
89 KnownNat (R.RecSize lts),
90 KnownSymbol label,
90 KnownSymbol label,
91 R.RecCopy lts lts res,
91 R.RecCopy lts lts res,
92 res ~ ((label := value) : lts),
92 res ~ ((label := value) : lts),
93 R.RemoveAccessTo label lts ~ lts
93 R.RemoveAccessTo label lts ~ lts
94− ) =>
94+ ) =>
95 label := value ->
95 label := value ->
96− Rec lts -> Rec res
96+ Rec lts ->
97+ Rec res
97−insert = R.combine . Rec
98+insert = R.combine . Rec
98
99
99-- | Insert a field into a record. Set it if it already exists
100-- | Insert a field into a record. Set it if it already exists
100--
101--
src/JRec/Internal.hs+20−5
@@ -32,6 +32,7 @@ import qualified Control.Monad.State as S
32import Data.Aeson
32import Data.Aeson
33import Data.Aeson.Types (Parser)
33import Data.Aeson.Types (Parser)
34import Data.Constraint
34import Data.Constraint
35+import Data.Maybe (catMaybes)
35import Data.Proxy
36import Data.Proxy
36import qualified Data.Text as T
37import qualified Data.Text as T
37import Data.Typeable
38import Data.Typeable
@@ -115,7 +116,7 @@ instance RecEq lts lts => Eq (Rec lts) where
115
116
116#ifdef WITH_AESON
117#ifdef WITH_AESON
117instance
118instance
118− ( RecApply lts lts ToJSON
119+ ( RecApply lts lts EncodeField
119 ) =>
120 ) =>
120 ToJSON (Rec lts)
121 ToJSON (Rec lts)
121 where
122 where
@@ -124,6 +125,7 @@ instance
124
125
125instance (RecSize lts ~ s, KnownNat s, RecJsonParse lts) => FromJSON (Rec lts) where
126instance (RecSize lts ~ s, KnownNat s, RecJsonParse lts) => FromJSON (Rec lts) where
126 parseJSON = recJsonParser defaultJSONOptions
127 parseJSON = recJsonParser defaultJSONOptions
128+
127#endif
129#endif
128
130
129instance RecNfData lts lts => NFData (Rec lts) where
131instance RecNfData lts lts => NFData (Rec lts) where
@@ -552,13 +554,26 @@ reflectRecFold _ f r =
552showRec :: forall lts. (RecApply lts lts Show) => Rec lts -> [(String, String)]
554showRec :: forall lts. (RecApply lts lts Show) => Rec lts -> [(String, String)]
553showRec = reflectRec @Show Proxy (\k v -> (k, show v))
555showRec = reflectRec @Show Proxy (\k v -> (k, show v))
554
556
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+
555−recToValue :: forall lts. (RecApply lts lts ToJSON) => JSONOptions -> Rec lts -> Value
570+recToValue :: forall lts. (RecApply lts lts EncodeField) => JSONOptions -> Rec lts -> Value
556recToValue options r =
571recToValue 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
558
573
559−recToEncoding :: forall lts. (RecApply lts lts ToJSON) => JSONOptions -> Rec lts -> Encoding
574+recToEncoding :: forall lts. (RecApply lts lts EncodeField) => JSONOptions -> Rec lts -> Encoding
560recToEncoding options r =
575recToEncoding 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
562
577
563recJsonParser ::
578recJsonParser ::
564 forall lts s.
579 forall lts s.
test/JRecSpec.hs+3−3
@@ -91,14 +91,14 @@ spec = do
91 describe "optional fields" $ do
91 describe "optional fields" $ do
92 it "encode" $ do
92 it "encode" $ do
93 encode (Rec (#a := (1 :: Int), #b := (Nothing :: Maybe Int)))
93 encode (Rec (#a := (1 :: Int), #b := (Nothing :: Maybe Int)))
94− `shouldBe` "{\"a\":1,\"b\":null}"
94+ `shouldBe` "{\"a\":1}"
95 it "encode" $ do
95 it "encode" $ do
96 encode (Rec (#a := (1 :: Int), #b := (Just 2 :: Maybe Int)))
96 encode (Rec (#a := (1 :: Int), #b := (Just 2 :: Maybe Int)))
97 `shouldBe` "{\"a\":1,\"b\":2}"
97 `shouldBe` "{\"a\":1,\"b\":2}"
98 it "decode" $ do
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}"
99 decode "{\"a\": 1}"
102 `shouldBe` Just (Rec (#a := (1 :: Int), #b := (Nothing :: Maybe Int)))
100 `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)))
103 decode "{\"a\": 1, \"b\": 2}"
103 decode "{\"a\": 1, \"b\": 2}"
104 `shouldBe` Just (Rec (#a := (1 :: Int), #b := (Just 2 :: Maybe Int)))
104 `shouldBe` Just (Rec (#a := (1 :: Int), #b := (Just 2 :: Maybe Int)))