Skip to content

Commit

Permalink
Merge pull request #228 from alissa-tung/master
Browse files Browse the repository at this point in the history
Use Aeson `>=2.0.0.0  && <2.1` and GitHub Actions
  • Loading branch information
swamp-agr committed Nov 11, 2021
2 parents 51f2108 + 7cc3b31 commit 9846955
Show file tree
Hide file tree
Showing 16 changed files with 143 additions and 239 deletions.
41 changes: 41 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: ci
on:
push:
branches:
- master
pull_request:

jobs:
cabal:
runs-on: ${{ matrix.os }}
strategy:
matrix:
ghc: ["8.6.5", "8.8.4", "8.10.4", "8.10.7"]
cabal: ["3.6.2.0"]
os: [ubuntu-latest, macOS-latest]
name: build and test (cabal)
steps:
- uses: actions/checkout@v2
- name: Run Haskell
uses: haskell/actions/setup@v1
with:
ghc-version: ${{ matrix.ghc }}
cabal-version: ${{ matrix.cabal }}
- run: |
cabal build --enable-tests && cabal test
stack:
name: build and test (stack)
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macOS-latest]
steps:
- uses: actions/checkout@v2
- uses: haskell/actions/setup@v1
with:
ghc-version: "8.10.7"
enable-stack: true
stack-version: "latest"
- run: |
stack build && stack test
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ cabal.sandbox.config
*.aux
*.hp
.stack-work/
stack.yaml.lock
155 changes: 0 additions & 155 deletions .travis.yml

This file was deleted.

8 changes: 4 additions & 4 deletions src/Data/Swagger.hs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ import Data.Swagger.Internal
-- In this library you can use @'mempty'@ for a default/empty value. For instance:
--
-- >>> encode (mempty :: Swagger)
-- "{\"swagger\":\"2.0\",\"info\":{\"version\":\"\",\"title\":\"\"}}"
-- "{\"swagger\":\"2.0\",\"info\":{\"title\":\"\",\"version\":\"\"}}"
--
-- As you can see some spec properties (e.g. @"version"@) are there even when the spec is empty.
-- That is because these properties are actually required ones.
Expand All @@ -153,12 +153,12 @@ import Data.Swagger.Internal
-- although it is not strictly necessary:
--
-- >>> encode mempty { _infoTitle = "Todo API", _infoVersion = "1.0" }
-- "{\"version\":\"1.0\",\"title\":\"Todo API\"}"
-- "{\"title\":\"Todo API\",\"version\":\"1.0\"}"
--
-- You can merge two values using @'mappend'@ or its infix version @('<>')@:
--
-- >>> encode $ mempty { _infoTitle = "Todo API" } <> mempty { _infoVersion = "1.0" }
-- "{\"version\":\"1.0\",\"title\":\"Todo API\"}"
-- "{\"title\":\"Todo API\",\"version\":\"1.0\"}"
--
-- This can be useful for combining specifications of endpoints into a whole API specification:
--
Expand Down Expand Up @@ -192,7 +192,7 @@ import Data.Swagger.Internal
-- & at 200 ?~ ("OK" & _Inline.schema ?~ Ref (Reference "User"))
-- & at 404 ?~ "User info not found")) ]
-- :}
-- "{\"swagger\":\"2.0\",\"info\":{\"version\":\"\",\"title\":\"\"},\"paths\":{\"/user\":{\"get\":{\"produces\":[\"application/json\"],\"responses\":{\"404\":{\"description\":\"User info not found\"},\"200\":{\"schema\":{\"$ref\":\"#/definitions/User\"},\"description\":\"OK\"}}}}},\"definitions\":{\"User\":{\"type\":\"string\"}}}"
-- "{\"swagger\":\"2.0\",\"info\":{\"title\":\"\",\"version\":\"\"},\"paths\":{\"/user\":{\"get\":{\"produces\":[\"application/json\"],\"responses\":{\"200\":{\"description\":\"OK\",\"schema\":{\"$ref\":\"#/definitions/User\"}},\"404\":{\"description\":\"User info not found\"}}}}},\"definitions\":{\"User\":{\"type\":\"string\"}}}"
--
-- In the snippet above we declare an API with a single path @/user@. This path provides method @GET@
-- which produces @application/json@ output. It should respond with code @200@ and body specified
Expand Down
3 changes: 2 additions & 1 deletion src/Data/Swagger/Internal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import Text.Read (readMaybe)

import Data.HashMap.Strict.InsOrd (InsOrdHashMap)
import qualified Data.HashMap.Strict.InsOrd as InsOrdHashMap
import qualified Data.Aeson.KeyMap as KM

import Generics.SOP.TH (deriveGeneric)
import Data.Swagger.Internal.AesonUtils (sopSwaggerGenericToJSON
Expand Down Expand Up @@ -1302,7 +1303,7 @@ instance FromJSON ParamOtherSchema where
instance FromJSON Responses where
parseJSON (Object o) = Responses
<$> o .:? "default"
<*> (parseJSON (Object (HashMap.delete "default" o)))
<*> parseJSON (Object (KM.delete "default" o))
parseJSON _ = empty

instance FromJSON Example where
Expand Down
37 changes: 21 additions & 16 deletions src/Data/Swagger/Internal/AesonUtils.hs
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,17 @@ import Prelude ()
import Prelude.Compat

import Control.Applicative ((<|>))
import Control.Lens (makeLenses, (^.))
import Control.Monad (unless)
import Data.Aeson (ToJSON(..), FromJSON(..), Value(..), Object, object, (.:), (.:?), (.!=), withObject)
import Control.Lens (makeLenses, (^.))
import Control.Monad (unless)
import Data.Aeson ( Encoding, FromJSON (..), ToJSON (..)
, Object, Series, Value (..)
, object, pairs, withObject
, (.!=), (.:), (.:?), (.=)
)
import Data.Aeson.Key (fromString, toString, fromText, toText)
import qualified Data.Aeson.KeyMap as KM
import Data.Aeson.Types (Parser, Pair)
import Data.Bifunctor (first)
import Data.Char (toLower, isUpper)
import Data.Foldable (traverse_)
import Data.Text (Text)
Expand All @@ -41,8 +48,6 @@ import qualified Data.Set as Set
import qualified Data.HashMap.Strict.InsOrd as InsOrd
import qualified Data.HashSet.InsOrd as InsOrdHS

import Data.Aeson (Encoding, pairs, (.=), Series)

-------------------------------------------------------------------------------
-- SwaggerAesonOptions
-------------------------------------------------------------------------------
Expand Down Expand Up @@ -105,7 +110,7 @@ sopSwaggerGenericToJSON
-> Value
sopSwaggerGenericToJSON x =
let ps = sopSwaggerGenericToJSON' opts (from x) (datatypeInfo proxy) (aesonDefaults proxy)
in object (opts ^. saoAdditionalPairs ++ ps)
in object $ (map $ first fromText) (opts ^. saoAdditionalPairs ++ (map $ first toText) ps)
where
proxy = Proxy :: Proxy a
opts = swaggerAesonOptions proxy
Expand All @@ -127,7 +132,7 @@ sopSwaggerGenericToJSONWithOpts
-> Value
sopSwaggerGenericToJSONWithOpts opts x =
let ps = sopSwaggerGenericToJSON' opts (from x) (datatypeInfo proxy) defs
in object (opts ^. saoAdditionalPairs ++ ps)
in object $ (map $ first fromText) (opts ^. saoAdditionalPairs ++ (map $ first toText) ps)
where
proxy = Proxy :: Proxy a
defs = hcpure (Proxy :: Proxy AesonDefaultValue) defaultValue
Expand Down Expand Up @@ -156,14 +161,14 @@ sopSwaggerGenericToJSON'' (SwaggerAesonOptions prefix _ sub) = go
go Nil Nil Nil = []
go (I x :* xs) (FieldInfo name :* names) (def :* defs)
| Just name' == sub = case json of
Object m -> HM.toList m ++ rest
Object m -> KM.toList m ++ rest
Null -> rest
_ -> error $ "sopSwaggerGenericToJSON: subjson is not an object: " ++ show json
-- If default value: omit it.
| Just x == def =
rest
| otherwise =
(T.pack name', json) : rest
(fromString name', json) : rest
where
json = toJSON x
name' = fieldNameModifier name
Expand Down Expand Up @@ -199,7 +204,7 @@ sopSwaggerGenericParseJSON = withObject "Swagger Record Object" $ \obj ->

parseAdditionalField :: Object -> (Text, Value) -> Parser ()
parseAdditionalField obj (k, v) = do
v' <- obj .: k
v' <- obj .: fromText k
unless (v == v') $ fail $
"Additonal field don't match for key " ++ T.unpack k
++ ": " ++ show v
Expand Down Expand Up @@ -230,10 +235,10 @@ sopSwaggerGenericParseJSON'' (SwaggerAesonOptions prefix _ sub) obj = go
go (FieldInfo name :* names) (def :* defs)
| Just name' == sub =
-- Note: we might strip fields of outer structure.
cons <$> (withDef $ parseJSON $ Object obj) <*> rest
cons <$> withDef (parseJSON $ Object obj) <*> rest
| otherwise = case def of
Just def' -> cons <$> obj .:? T.pack name' .!= def' <*> rest
Nothing -> cons <$> obj .: T.pack name' <*> rest
Just def' -> cons <$> obj .:? fromString name' .!= def' <*> rest
Nothing -> cons <$> obj .: fromString name' <*> rest
where
cons h t = I h :* t
name' = fieldNameModifier name
Expand Down Expand Up @@ -264,7 +269,7 @@ sopSwaggerGenericToEncoding
-> Encoding
sopSwaggerGenericToEncoding x =
let ps = sopSwaggerGenericToEncoding' opts (from x) (datatypeInfo proxy) (aesonDefaults proxy)
in pairs (pairsToSeries (opts ^. saoAdditionalPairs) <> ps)
in pairs (pairsToSeries ((map $ first fromText) (opts ^. saoAdditionalPairs)) <> ps)
where
proxy = Proxy :: Proxy a
opts = swaggerAesonOptions proxy
Expand Down Expand Up @@ -296,14 +301,14 @@ sopSwaggerGenericToEncoding'' (SwaggerAesonOptions prefix _ sub) = go
go Nil Nil Nil = mempty
go (I x :* xs) (FieldInfo name :* names) (def :* defs)
| Just name' == sub = case toJSON x of
Object m -> pairsToSeries (HM.toList m) <> rest
Object m -> pairsToSeries (KM.toList m) <> rest
Null -> rest
_ -> error $ "sopSwaggerGenericToJSON: subjson is not an object: " ++ show (toJSON x)
-- If default value: omit it.
| Just x == def =
rest
| otherwise =
(T.pack name' .= x) <> rest
(fromString name' .= x) <> rest
where
name' = fieldNameModifier name
rest = go xs names defs
Expand Down
4 changes: 2 additions & 2 deletions src/Data/Swagger/Internal/ParamSchema.hs
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ instance ToParamSchema a => ToParamSchema (HashSet a) where

-- |
-- >>> encode $ toParamSchema (Proxy :: Proxy ())
-- "{\"type\":\"string\",\"enum\":[\"_\"]}"
-- "{\"enum\":[\"_\"],\"type\":\"string\"}"
instance ToParamSchema () where
toParamSchema _ = mempty
& type_ ?~ SwaggerString
Expand All @@ -286,7 +286,7 @@ instance ToParamSchema UUID where
-- >>> :set -XDeriveGeneric
-- >>> data Color = Red | Blue deriving Generic
-- >>> encode $ genericToParamSchema defaultSchemaOptions (Proxy :: Proxy Color)
-- "{\"type\":\"string\",\"enum\":[\"Red\",\"Blue\"]}"
-- "{\"enum\":[\"Red\",\"Blue\"],\"type\":\"string\"}"
genericToParamSchema :: forall a t. (Generic a, GToParamSchema (Rep a)) => SchemaOptions -> Proxy a -> ParamSchema t
genericToParamSchema opts _ = gtoParamSchema opts (Proxy :: Proxy (Rep a)) mempty

Expand Down
Loading

0 comments on commit 9846955

Please sign in to comment.