@@ -1,3 +1,4 @@
1{-# LANGUAGE DataKinds #-}
2{-# LANGUAGE DataKinds #-}
2{-# LANGUAGE FlexibleContexts #-}
3{-# LANGUAGE FlexibleContexts #-}
3{-# LANGUAGE GADTs #-}
4{-# LANGUAGE GADTs #-}
@@ -8,6 +9,9 @@ module Data.Swagger.Internal.AesonUtils (
8 -- * Generic functions
9 -- * Generic functions
9 AesonDefaultValue(..),
10 AesonDefaultValue(..),
10 sopSwaggerGenericToJSON,
11 sopSwaggerGenericToJSON,
12+#if MIN_VERSION_aeson(0,10,0)
13+ sopSwaggerGenericToEncoding,
11 sopSwaggerGenericToJSONWithOpts,
15 sopSwaggerGenericToJSONWithOpts,
12 sopSwaggerGenericParseJSON,
16 sopSwaggerGenericParseJSON,
13 -- * Options
17 -- * Options
@@ -26,7 +30,7 @@ import Control.Applicative ((<|>))
26import Control.Lens (makeLenses, (^.))
30import Control.Lens (makeLenses, (^.))
27import Control.Monad (unless)
31import Control.Monad (unless)
28import Data.Aeson (ToJSON(..), FromJSON(..), Value(..), Object, object, (.:), (.:?), (.!=), withObject)
32import Data.Aeson (ToJSON(..), FromJSON(..), Value(..), Object, object, (.:), (.:?), (.!=), withObject)
29−import Data.Aeson.Types (Parser)
33+import Data.Aeson.Types (Parser, Pair)
30import Data.Char (toLower, isUpper)
34import Data.Char (toLower, isUpper)
31import Data.Text (Text)
35import Data.Text (Text)
@@ -37,6 +41,12 @@ import qualified Data.HashMap.Strict as HM
37import qualified Data.Set as Set
41import qualified Data.Set as Set
38import qualified Data.HashMap.Strict.InsOrd as InsOrd
42import qualified Data.HashMap.Strict.InsOrd as InsOrd
44+#if MIN_VERSION_aeson(0,10,0)
45+import Data.Aeson (Encoding, pairs, (.=), Series)
46+import Data.Monoid ((<>))
47+import Data.Foldable (foldMap)
40-------------------------------------------------------------------------------
50-------------------------------------------------------------------------------
41-- SwaggerAesonOptions
51-- SwaggerAesonOptions
42-------------------------------------------------------------------------------
52-------------------------------------------------------------------------------
@@ -132,7 +142,7 @@ sopSwaggerGenericToJSON'
132 -> SOP I '[xs]
142 -> SOP I '[xs]
133 -> DatatypeInfo '[xs]
143 -> DatatypeInfo '[xs]
134 -> POP Maybe '[xs]
144 -> POP Maybe '[xs]
135− -> [(Text, Value)]
145+ -> [Pair]
136sopSwaggerGenericToJSON' opts (SOP (Z fields)) (ADT _ _ (Record _ fieldsInfo :* Nil)) (POP (defs :* Nil)) =
146sopSwaggerGenericToJSON' opts (SOP (Z fields)) (ADT _ _ (Record _ fieldsInfo :* Nil)) (POP (defs :* Nil)) =
137 sopSwaggerGenericToJSON'' opts fields fieldsInfo defs
147 sopSwaggerGenericToJSON'' opts fields fieldsInfo defs
@@ -142,10 +152,10 @@ sopSwaggerGenericToJSON''
142 -> NP I xs
152 -> NP I xs
143 -> NP FieldInfo xs
153 -> NP FieldInfo xs
144 -> NP Maybe xs
154 -> NP Maybe xs
145− -> [(Text, Value)]
155+ -> [Pair]
146sopSwaggerGenericToJSON'' (SwaggerAesonOptions prefix _ sub) = go
156sopSwaggerGenericToJSON'' (SwaggerAesonOptions prefix _ sub) = go
148− go :: (All ToJSON ys, All Eq ys) => NP I ys -> NP FieldInfo ys -> NP Maybe ys -> [(Text, Value)]
158+ go :: (All ToJSON ys, All Eq ys) => NP I ys -> NP FieldInfo ys -> NP Maybe ys -> [Pair]
149 go Nil Nil Nil = []
159 go Nil Nil Nil = []
150 go (I x :* xs) (FieldInfo name :* names) (def :* defs)
160 go (I x :* xs) (FieldInfo name :* names) (def :* defs)
151 | Just name' == sub = case json of
161 | Just name' == sub = case json of
@@ -240,3 +250,72 @@ sopSwaggerGenericParseJSON'' (SwaggerAesonOptions prefix _ sub) obj = go
240 modifier = lowerFirstUppers . drop (length prefix)
250 modifier = lowerFirstUppers . drop (length prefix)
241 lowerFirstUppers s = map toLower x ++ y
251 lowerFirstUppers s = map toLower x ++ y
242 where (x, y) = span isUpper s
252 where (x, y) = span isUpper s
254+-------------------------------------------------------------------------------
256+-------------------------------------------------------------------------------
258+#if MIN_VERSION_aeson(0,10,0)
260+sopSwaggerGenericToEncoding
264+ , HasSwaggerAesonOptions a
265+ , All2 ToJSON (Code a)
271+sopSwaggerGenericToEncoding x =
272+ let ps = sopSwaggerGenericToEncoding' opts (from x) (datatypeInfo proxy) (aesonDefaults proxy)
273+ in pairs (pairsToSeries (opts ^. saoAdditionalPairs) <> ps)
275+ proxy = Proxy :: Proxy a
276+ opts = swaggerAesonOptions proxy
278+pairsToSeries :: [Pair] -> Series
279+pairsToSeries = foldMap (\(k, v) -> (k .= v))
281+sopSwaggerGenericToEncoding'
282+ :: (All2 ToJSON '[xs], All2 Eq '[xs])
283+ => SwaggerAesonOptions
285+ -> DatatypeInfo '[xs]
288+sopSwaggerGenericToEncoding' opts (SOP (Z fields)) (ADT _ _ (Record _ fieldsInfo :* Nil)) (POP (defs :* Nil)) =
289+ sopSwaggerGenericToEncoding'' opts fields fieldsInfo defs
291+sopSwaggerGenericToEncoding''
292+ :: (All ToJSON xs, All Eq xs)
293+ => SwaggerAesonOptions
298+sopSwaggerGenericToEncoding'' (SwaggerAesonOptions prefix _ sub) = go
300+ go :: (All ToJSON ys, All Eq ys) => NP I ys -> NP FieldInfo ys -> NP Maybe ys -> Series
301+ go Nil Nil Nil = mempty
302+ go (I x :* xs) (FieldInfo name :* names) (def :* defs)
303+ | Just name' == sub = case toJSON x of
304+ Object m -> pairsToSeries (HM.toList m) <> rest
306+ _ -> error $ "sopSwaggerGenericToJSON: subjson is not an object: " ++ show (toJSON x)
307+ -- If default value: omit it.
311+ (T.pack name' .= x) <> rest
313+ name' = fieldNameModifier name
314+ rest = go xs names defs
316+ fieldNameModifier = modifier . drop 1
317+ modifier = lowerFirstUppers . drop (length prefix)
318+ lowerFirstUppers s = map toLower x ++ y
319+ where (x, y) = span isUpper s