@@ -97,9 +97,9 @@ import Data.Functor ( fmap )
9797import Data.Int ( Int )
9898import Data.Either ( Either(Left, Right) )
9999import Data.List ( (++), foldl, foldl', intercalate
100− , length, map, zip, genericLength, all
100+ , length, map, zip, genericLength, all, partition
101101 )
102−import Data.Maybe ( Maybe(Nothing, Just) )
102+import Data.Maybe ( Maybe(Nothing, Just), catMaybes )
103103import Prelude ( String, (-), Integer, fromIntegral, error )
104104import Text.Printf ( printf )
105105import Text.Show ( show )
@@ -287,23 +287,52 @@ encodeArgs opts multiCons (NormalC conName ts) = do
287287-- Records.
288288encodeArgs opts multiCons (RecC conName ts) = do
289289 args <- mapM newName ["arg" ++ show n | (_, n) <- zip ts [1 :: Integer ..]]
290− let js = [ infixApp ([|T.pack|] `appE` fieldNameExp opts field)
291− [|(.=)|]
292− (varE arg)
293− | (arg, (field, _, _)) <- zip args ts
294− ]
295− exp = [|object|] `appE` listE js
290+ let exp = [|object|] `appE` pairs
291+
292+ pairs | omitNothingFields opts = infixApp maybeFields
293+ [|(++)|]
294+ restFields
295+ | otherwise = listE $ map toPair argCons
296+
297+ argCons = zip args ts
298+
299+ maybeFields = [|catMaybes|] `appE` listE (map maybeToPair maybes)
300+
301+ restFields = listE $ map toPair rest
302+
303+ (maybes, rest) = partition isMaybe argCons
304+
305+ isMaybe (_, (_, _, AppT (ConT t) _)) = t == ''Maybe
306+ isMaybe _ = False
307+
308+ maybeToPair (arg, (field, _, _)) =
309+ infixApp (infixE (Just $ toFieldName field)
310+ [|(.=)|]
311+ Nothing)
312+ [|(<$>)|]
313+ (varE arg)
314+
315+ toPair (arg, (field, _, _)) =
316+ infixApp (toFieldName field)
317+ [|(.=)|]
318+ (varE arg)
319+
320+ toFieldName field = [|T.pack|] `appE` fieldNameExp opts field
321+
296322 match (conP conName $ map varP args)
297323 ( normalB
298324 $ if multiCons
299325 then case sumEncoding opts of
300326 TwoElemArray -> [|toJSON|] `appE` tupE [conStr opts conName, exp]
301327 ObjectWithType{typeFieldName} ->
302− [|object|] `appE` listE
303− ( infixApp [|T.pack typeFieldName|] [|(.=)|]
304− (conStr opts conName)
305− : js
306− )
328+ [|object|] `appE`
329+ -- TODO: Maybe throw an error in case
330+ -- typeFieldName overwrites a field in pairs.
331+ infixApp (infixApp [|T.pack typeFieldName|]
332+ [|(.=)|]
333+ (conStr opts conName))
334+ [|(:)|]
335+ pairs
307336 ObjectWithSingleField ->
308337 [|object|] `appE` listE
309338 [ infixApp (conTxt opts conName) [|(.=)|] exp ]