@@ -114,11 +114,11 @@ module Data.Aeson.TH
114
114
115
115
import Data.Aeson.Internal.Prelude
116
116
117
+ import Data.Bool (bool )
117
118
import Data.Char (ord )
118
119
import Data.Aeson (Object , (.:) , FromJSON (.. ), FromJSON1 (.. ), FromJSON2 (.. ), ToJSON (.. ), ToJSON1 (.. ), ToJSON2 (.. ))
119
120
import Data.Aeson.Types (Options (.. ), Parser , SumEncoding (.. ), Value (.. ), defaultOptions , defaultTaggedObject )
120
121
import Data.Aeson.Types.Internal ((<?>) , JSONPathElement (Key ))
121
- import Data.Aeson.Types.FromJSON (parseOptionalFieldWith )
122
122
import Data.Aeson.Types.ToJSON (fromPairs , pair )
123
123
import Data.Aeson.Key (Key )
124
124
import qualified Data.Aeson.Key as Key
@@ -135,9 +135,6 @@ import Text.Printf (printf)
135
135
import qualified Data.Aeson.Encoding.Internal as E
136
136
import qualified Data.List.NonEmpty as NE (length , reverse )
137
137
import qualified Data.Map as M (fromList , keys , lookup , singleton , size )
138
- #if !MIN_VERSION_base(4,16,0)
139
- import qualified Data.Semigroup as Semigroup (Option (.. ))
140
- #endif
141
138
import qualified Data.Set as Set (empty , insert , member )
142
139
import qualified Data.Text as T (pack , unpack )
143
140
import qualified Data.Vector as V (unsafeIndex , null , length , create , empty )
@@ -456,40 +453,24 @@ argsToValue letInsert target jc tvMap opts multiCons
456
453
(True ,True ,[_]) -> argsToValue letInsert target jc tvMap opts multiCons
457
454
(info{constructorVariant = NormalConstructor })
458
455
_ -> do
456
+
459
457
argTys' <- mapM resolveTypeSynonyms argTys
460
458
args <- newNameList " arg" $ length argTys'
461
- let pairs | omitNothingFields opts = infixApp maybeFields
462
- [| (Monoid. <>) | ]
463
- restFields
464
- | otherwise = mconcatE (map pureToPair argCons)
465
-
466
- argCons = zip3 (map varE args) argTys' fields
467
-
468
- maybeFields = mconcatE (map maybeToPair maybes)
469
-
470
- restFields = mconcatE (map pureToPair rest)
471
-
472
- (maybes0, rest0) = partition isMaybe argCons
473
- #if MIN_VERSION_base(4,16,0)
474
- maybes = maybes0
475
- rest = rest0
476
- #else
477
- (options, rest) = partition isOption rest0
478
- maybes = maybes0 ++ map optionToMaybe options
479
- #endif
480
-
481
- maybeToPair = toPairLifted True
482
- pureToPair = toPairLifted False
483
-
484
- toPairLifted lifted (arg, argTy, field) =
485
- let toValue = dispatchToJSON target jc conName tvMap argTy
486
- fieldName = fieldLabel opts field
487
- e arg' = pairE letInsert target fieldName (toValue `appE` arg')
488
- in if lifted
489
- then do
490
- x <- newName " x"
491
- [| maybe mempty | ] `appE` lam1E (varP x) (e (varE x)) `appE` arg
492
- else e arg
459
+ let argCons = zip3 (map varE args) argTys' fields
460
+
461
+ toPair (arg, argTy, fld) =
462
+ let fieldName = fieldLabel opts fld
463
+ toValue = dispatchToJSON target jc conName tvMap argTy
464
+ omitFn
465
+ | omitNothingFields opts = [| omitField | ]
466
+ | otherwise = [| const False | ]
467
+ in
468
+ [| \ f x arg' -> bool x mempty (f arg') | ]
469
+ `appE` omitFn
470
+ `appE` pairE letInsert target fieldName (toValue `appE` arg)
471
+ `appE` arg
472
+
473
+ pairs = mconcatE (map toPair argCons)
493
474
494
475
match (conP conName $ map varP args)
495
476
(normalB $ recordSumToValue letInsert target opts multiCons (null argTys) conName pairs)
@@ -514,19 +495,6 @@ argsToValue letInsert target jc tvMap opts multiCons
514
495
)
515
496
[]
516
497
517
- isMaybe :: (a , Type , b ) -> Bool
518
- isMaybe (_, AppT (ConT t) _, _) = t == ''Maybe
519
- isMaybe _ = False
520
-
521
- #if !MIN_VERSION_base(4,16,0)
522
- isOption :: (a , Type , b ) -> Bool
523
- isOption (_, AppT (ConT t) _, _) = t == ''Semigroup. Option
524
- isOption _ = False
525
-
526
- optionToMaybe :: (ExpQ , b , c ) -> (ExpQ , b , c )
527
- optionToMaybe (a, b, c) = ([| Semigroup. getOption| ] `appE` a, b, c)
528
- #endif
529
-
530
498
(<^>) :: ExpQ -> ExpQ -> ExpQ
531
499
(<^>) a b = infixApp a [| (E. ><) | ] b
532
500
infixr 6 <^>
@@ -953,6 +921,9 @@ parseRecord jc tvMap argTys opts tName conName fields obj inTaggedObject =
953
921
(infixApp (conE conName) [| (<$>) | ] x)
954
922
xs
955
923
where
924
+ defVal = case jc of
925
+ JSONClass From Arity0 -> [| omittedField| ]
926
+ _ -> [| Nothing | ]
956
927
tagFieldNameAppender =
957
928
if inTaggedObject then (tagFieldName (sumEncoding opts) : ) else id
958
929
knownFields = appE [| KM. fromList| ] $ listE $
@@ -970,6 +941,7 @@ parseRecord jc tvMap argTys opts tName conName fields obj inTaggedObject =
970
941
[]
971
942
]
972
943
x: xs = [ [| lookupField| ]
944
+ `appE` defVal
973
945
`appE` dispatchParseJSON jc conName tvMap argTy
974
946
`appE` litE (stringL $ show tName)
975
947
`appE` litE (stringL $ constructorTagModifier opts $ nameBase conName)
@@ -1137,28 +1109,14 @@ parseTypeMismatch tName conName expected actual =
1137
1109
, actual
1138
1110
]
1139
1111
1140
- class LookupField a where
1141
- lookupField :: (Value -> Parser a ) -> String -> String
1142
- -> Object -> Key -> Parser a
1143
-
1144
- instance {-# OVERLAPPABLE #-} LookupField a where
1145
- lookupField = lookupFieldWith
1146
-
1147
- instance {-# INCOHERENT #-} LookupField (Maybe a ) where
1148
- lookupField pj _ _ = parseOptionalFieldWith pj
1149
-
1150
- #if !MIN_VERSION_base(4,16,0)
1151
- instance {-# INCOHERENT #-} LookupField (Semigroup. Option a ) where
1152
- lookupField pj tName rec obj key =
1153
- fmap Semigroup. Option
1154
- (lookupField (fmap Semigroup. getOption . pj) tName rec obj key)
1155
- #endif
1156
-
1157
- lookupFieldWith :: (Value -> Parser a ) -> String -> String
1158
- -> Object -> Key -> Parser a
1159
- lookupFieldWith pj tName rec obj key =
1112
+ lookupField :: Maybe a -> (Value -> Parser a ) -> String -> String
1113
+ -> Object -> Key -> Parser a
1114
+ lookupField maybeDefault pj tName rec obj key =
1160
1115
case KM. lookup key obj of
1161
- Nothing -> unknownFieldFail tName rec (Key. toString key)
1116
+ Nothing ->
1117
+ case maybeDefault of
1118
+ Nothing -> unknownFieldFail tName rec (Key. toString key)
1119
+ Just x -> pure x
1162
1120
Just v -> pj v <?> Key key
1163
1121
1164
1122
unknownFieldFail :: String -> String -> String -> Parser fail
0 commit comments