on master help sign in
Implement tagSingleConstructors for Generics
commit3392b6d1e553c2443f008f52c147ef2b52641a96 authorlyxia <lysxia@gmail.com> dateSat 18 Mar 2017, 19:17 (10 years ago) parent235d387
2 files changed+38−13
Data/Aeson/Types/FromJSON.hs+26−13 Data/Aeson/Types/ToJSON.hs+12
Data/Aeson/Types/FromJSON.hs+26−13
@@ -791,6 +791,19 @@ instance GFromJSON arity U1 where
791791 | isEmptyArray v = pure U1
792792 | otherwise = typeMismatch "unit constructor (U1)" v
793793
794+instance ( ConsFromJSON arity a
795+ , AllNullary (C1 c a) allNullary
796+ , ParseSum arity (C1 c a) allNullary
797+ ) => GFromJSON arity (D1 d (C1 c a)) where
798+ -- The option 'tagSingleConstructors' determines whether to wrap
799+ -- a single-constructor type.
800+ gParseJSON opts fargs
801+ | tagSingleConstructors opts
802+ = fmap M1
803+ . (unTagged :: Tagged allNullary (Parser (C1 c a p)) -> Parser (C1 c a p))
804+ . parseSum opts fargs
805+ | otherwise = fmap M1 . fmap M1 . consParseJSON opts fargs
806+
794807instance (ConsFromJSON arity a) => GFromJSON arity (C1 c a) where
795808 -- Constructors need to be decoded differently depending on whether they're
796809 -- a record or not. This distinction is made by consParseJSON:
@@ -837,19 +850,19 @@ class ParseSum arity f allNullary where
837850 parseSum :: Options -> FromArgs arity a
838851 -> Value -> Tagged allNullary (Parser (f a))
839852
840−instance ( SumFromString (a :+: b)
841− , FromPair arity (a :+: b)
842− , FromTaggedObject arity (a :+: b)
843− , FromUntaggedValue arity (a :+: b)
844− ) => ParseSum arity (a :+: b) True where
853+instance ( SumFromString f
854+ , FromPair arity f
855+ , FromTaggedObject arity f
856+ , FromUntaggedValue arity f
857+ ) => ParseSum arity f True where
845858 parseSum opts fargs
846859 | allNullaryToStringTag opts = Tagged . parseAllNullarySum opts
847860 | otherwise = Tagged . parseNonAllNullarySum opts fargs
848861
849−instance ( FromPair arity (a :+: b)
850− , FromTaggedObject arity (a :+: b)
851− , FromUntaggedValue arity (a :+: b)
852− ) => ParseSum arity (a :+: b) False where
862+instance ( FromPair arity f
863+ , FromTaggedObject arity f
864+ , FromUntaggedValue arity f
865+ ) => ParseSum arity f False where
853866 parseSum opts fargs = Tagged . parseNonAllNullarySum opts fargs
854867
855868--------------------------------------------------------------------------------
@@ -875,11 +888,11 @@ instance (Constructor c) => SumFromString (C1 c U1) where
875888
876889--------------------------------------------------------------------------------
877890
878−parseNonAllNullarySum :: ( FromPair arity (a :+: b)
879− , FromTaggedObject arity (a :+: b)
880− , FromUntaggedValue arity (a :+: b)
891+parseNonAllNullarySum :: ( FromPair arity f
892+ , FromTaggedObject arity f
893+ , FromUntaggedValue arity f
881894 ) => Options -> FromArgs arity c
882− -> Value -> Parser ((a :+: b) c)
895+ -> Value -> Parser (f c)
883896parseNonAllNullarySum opts fargs =
884897 case sumEncoding opts of
885898 TaggedObject{..} ->
Data/Aeson/Types/ToJSON.hs+12
@@ -659,6 +659,18 @@ instance GToJSON enc One Par1 where
659659 -- function passed in as an argument:
660660 gToJSON _opts (To1Args tj _) = tj . unPar1
661661
662+instance ( ConsToJSON enc arity a
663+ , AllNullary (C1 c a) allNullary
664+ , SumToJSON enc arity (C1 c a) allNullary
665+ ) => GToJSON enc arity (D1 d (C1 c a)) where
666+ -- The option 'tagSingleConstructors' determines whether to wrap
667+ -- a single-constructor type.
668+ gToJSON opts targs
669+ | tagSingleConstructors opts = (unTagged :: Tagged allNullary enc -> enc)
670+ . sumToJSON opts targs
671+ . unM1
672+ | otherwise = consToJSON opts targs . unM1 . unM1
673+
662674instance (ConsToJSON enc arity a) => GToJSON enc arity (C1 c a) where
663675 -- Constructors need to be encoded differently depending on whether they're
664676 -- a record or not. This distinction is made by 'consToJSON':