Skip to content

Commit 3392b6d

Browse files
committed
Implement tagSingleConstructors for Generics
1 parent 235d387 commit 3392b6d

File tree

2 files changed

+38
-13
lines changed

2 files changed

+38
-13
lines changed

Data/Aeson/Types/FromJSON.hs

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
794807
instance (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)
883896
parseNonAllNullarySum opts fargs =
884897
case sumEncoding opts of
885898
TaggedObject{..} ->

Data/Aeson/Types/ToJSON.hs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
662674
instance (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':

0 commit comments

Comments
 (0)