diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,8 @@
+0.2
+---
+* Add `Data.Swagger.Lens`
+* Support references
+* Fixes:
+    * Fix `FromJSON SwaggerHost` instance
+    * Add missing `Maybe`s for field types
+    * Decode petstore swagger.json successfully
diff --git a/src/Data/Swagger.hs b/src/Data/Swagger.hs
--- a/src/Data/Swagger.hs
+++ b/src/Data/Swagger.hs
@@ -70,6 +70,10 @@
   -- * External documentation
   SwaggerExternalDocs(..),
 
+  -- * References
+  SwaggerReference(..),
+  SwaggerReferenced(..),
+
   -- * Miscellaneous
   SwaggerMimeList(..),
   URL(..),
diff --git a/src/Data/Swagger/Internal.hs b/src/Data/Swagger/Internal.hs
--- a/src/Data/Swagger/Internal.hs
+++ b/src/Data/Swagger/Internal.hs
@@ -35,61 +35,61 @@
 data Swagger = Swagger
   { -- | Provides metadata about the API.
     -- The metadata can be used by the clients if needed.
-    swaggerInfo :: SwaggerInfo
+    _swaggerInfo :: SwaggerInfo
 
     -- | The host (name or ip) serving the API. It MAY include a port.
     -- If the host is not included, the host serving the documentation is to be used (including the port).
-  , swaggerHost :: Maybe SwaggerHost
+  , _swaggerHost :: Maybe SwaggerHost
 
     -- | The base path on which the API is served, which is relative to the host.
     -- If it is not included, the API is served directly under the host.
     -- The value MUST start with a leading slash (/).
-  , swaggerBasePath :: Maybe FilePath
+  , _swaggerBasePath :: Maybe FilePath
 
     -- | The transfer protocol of the API.
     -- If the schemes is not included, the default scheme to be used is the one used to access the Swagger definition itself.
-  , swaggerSchemes :: Maybe [SwaggerScheme]
+  , _swaggerSchemes :: Maybe [SwaggerScheme]
 
     -- | A list of MIME types the APIs can consume.
     -- This is global to all APIs but can be overridden on specific API calls.
-  , swaggerConsumes :: SwaggerMimeList
+  , _swaggerConsumes :: SwaggerMimeList
 
     -- | A list of MIME types the APIs can produce.
     -- This is global to all APIs but can be overridden on specific API calls. 
-  , swaggerProduces :: SwaggerMimeList
+  , _swaggerProduces :: SwaggerMimeList
 
     -- | The available paths and operations for the API.
-  , swaggerPaths :: SwaggerPaths
+  , _swaggerPaths :: SwaggerPaths
 
     -- | An object to hold data types produced and consumed by operations.
-  , swaggerDefinitions :: HashMap Text SwaggerSchema
+  , _swaggerDefinitions :: HashMap Text SwaggerSchema
 
     -- | An object to hold parameters that can be used across operations.
     -- This property does not define global parameters for all operations.
-  , swaggerParameters :: HashMap Text SwaggerParameter
+  , _swaggerParameters :: HashMap Text SwaggerParameter
 
     -- | An object to hold responses that can be used across operations.
     -- This property does not define global responses for all operations.
-  , swaggerResponses :: HashMap Text SwaggerResponse
+  , _swaggerResponses :: HashMap Text SwaggerResponse
 
     -- | Security scheme definitions that can be used across the specification.
-  , swaggerSecurityDefinitions :: HashMap Text SwaggerSecurityScheme
+  , _swaggerSecurityDefinitions :: HashMap Text SwaggerSecurityScheme
 
     -- | A declaration of which security schemes are applied for the API as a whole.
     -- The list of values describes alternative security schemes that can be used
     -- (that is, there is a logical OR between the security requirements).
     -- Individual operations can override this definition.
-  , swaggerSecurity :: [SwaggerSecurityRequirement]
+  , _swaggerSecurity :: [SwaggerSecurityRequirement]
 
     -- | A list of tags used by the specification with additional metadata.
     -- The order of the tags can be used to reflect on their order by the parsing tools.
     -- Not all tags that are used by the Operation Object must be declared.
     -- The tags that are not declared may be organized randomly or based on the tools' logic.
     -- Each tag name in the list MUST be unique.
-  , swaggerTags :: [SwaggerTag]
+  , _swaggerTags :: [SwaggerTag]
 
     -- | Additional external documentation.
-  , swaggerExternalDocs :: Maybe SwaggerExternalDocs
+  , _swaggerExternalDocs :: Maybe SwaggerExternalDocs
   } deriving (Eq, Show, Generic)
 
 -- | The object provides metadata about the API.
@@ -97,51 +97,51 @@
 -- and can be presented in the Swagger-UI for convenience.
 data SwaggerInfo = SwaggerInfo
   { -- | The title of the application.
-    swaggerInfoTitle :: Text
+    _swaggerInfoTitle :: Text
 
     -- | A short description of the application.
     -- GFM syntax can be used for rich text representation.
-  , swaggerInfoDescription :: Maybe Text
+  , _swaggerInfoDescription :: Maybe Text
 
     -- | The Terms of Service for the API.
-  , swaggerInfoTermsOfService :: Maybe Text
+  , _swaggerInfoTermsOfService :: Maybe Text
 
     -- | The contact information for the exposed API.
-  , swaggerInfoContact :: Maybe SwaggerContact
+  , _swaggerInfoContact :: Maybe SwaggerContact
 
     -- | The license information for the exposed API.
-  , swaggerInfoLicense :: Maybe SwaggerLicense
+  , _swaggerInfoLicense :: Maybe SwaggerLicense
 
     -- | Provides the version of the application API
     -- (not to be confused with the specification version).
-  , swaggerInfoVersion :: Text
+  , _swaggerInfoVersion :: Text
   } deriving (Eq, Show, Generic)
 
 -- | Contact information for the exposed API.
 data SwaggerContact = SwaggerContact
   { -- | The identifying name of the contact person/organization.
-    swaggerContactName  :: Maybe Text
+    _swaggerContactName  :: Maybe Text
 
     -- | The URL pointing to the contact information.
-  , swaggerContactUrl   :: Maybe URL
+  , _swaggerContactUrl   :: Maybe URL
 
     -- | The email address of the contact person/organization.
-  , swaggerContactEmail :: Maybe Text
+  , _swaggerContactEmail :: Maybe Text
   } deriving (Eq, Show)
 
 -- | License information for the exposed API.
 data SwaggerLicense = SwaggerLicense
   { -- | The license name used for the API.
-    swaggerLicenseName :: Text
+    _swaggerLicenseName :: Text
 
     -- | A URL to the license used for the API.
-  , swaggerLicenseUrl :: Maybe URL
+  , _swaggerLicenseUrl :: Maybe URL
   } deriving (Eq, Show)
 
 -- | The host (name or ip) serving the API. It MAY include a port.
 data SwaggerHost = SwaggerHost
-  { swaggerHostName :: HostName         -- ^ Host name.
-  , swaggerHostPort :: Maybe PortNumber -- ^ Optional port.
+  { _swaggerHostName :: HostName         -- ^ Host name.
+  , _swaggerHostPort :: Maybe PortNumber -- ^ Optional port.
   } deriving (Eq, Show)
 
 -- | The transfer protocol of the API.
@@ -156,7 +156,7 @@
 data SwaggerPaths = SwaggerPaths
   { -- | Holds the relative paths to the individual endpoints.
     -- The path is appended to the @'swaggerBasePath'@ in order to construct the full URL.
-    swaggerPathsMap         :: HashMap FilePath SwaggerPathItem
+    _swaggerPathsMap         :: HashMap FilePath SwaggerPathItem
   } deriving (Eq, Show, Generic)
 
 -- | Describes the operations available on a single path.
@@ -165,91 +165,91 @@
 -- but they will not know which operations and parameters are available.
 data SwaggerPathItem = SwaggerPathItem
   { -- | A definition of a GET operation on this path.
-    swaggerPathItemGet :: Maybe SwaggerOperation
+    _swaggerPathItemGet :: Maybe SwaggerOperation
 
     -- | A definition of a PUT operation on this path.
-  , swaggerPathItemPut :: Maybe SwaggerOperation
+  , _swaggerPathItemPut :: Maybe SwaggerOperation
 
     -- | A definition of a POST operation on this path.
-  , swaggerPathItemPost :: Maybe SwaggerOperation
+  , _swaggerPathItemPost :: Maybe SwaggerOperation
 
     -- | A definition of a DELETE operation on this path.
-  , swaggerPathItemDelete :: Maybe SwaggerOperation
+  , _swaggerPathItemDelete :: Maybe SwaggerOperation
 
     -- | A definition of a OPTIONS operation on this path.
-  , swaggerPathItemOptions :: Maybe SwaggerOperation
+  , _swaggerPathItemOptions :: Maybe SwaggerOperation
 
     -- | A definition of a HEAD operation on this path.
-  , swaggerPathItemHead :: Maybe SwaggerOperation
+  , _swaggerPathItemHead :: Maybe SwaggerOperation
 
     -- | A definition of a PATCH operation on this path.
-  , swaggerPathItemPatch :: Maybe SwaggerOperation
+  , _swaggerPathItemPatch :: Maybe SwaggerOperation
 
     -- | A list of parameters that are applicable for all the operations described under this path.
     -- These parameters can be overridden at the operation level, but cannot be removed there.
     -- The list MUST NOT include duplicated parameters.
     -- A unique parameter is defined by a combination of a name and location.
-  , swaggerPathItemParameters :: [SwaggerParameter]
+  , _swaggerPathItemParameters :: [SwaggerReferenced SwaggerParameter]
   } deriving (Eq, Show, Generic)
 
 -- | Describes a single API operation on a path.
 data SwaggerOperation = SwaggerOperation
   { -- | A list of tags for API documentation control.
     -- Tags can be used for logical grouping of operations by resources or any other qualifier.
-    swaggerOperationTags :: [Text]
+    _swaggerOperationTags :: [Text]
 
     -- | A short summary of what the operation does.
     -- For maximum readability in the swagger-ui, this field SHOULD be less than 120 characters.
-  , swaggerOperationSummary :: Maybe Text
+  , _swaggerOperationSummary :: Maybe Text
 
     -- | A verbose explanation of the operation behavior.
     -- GFM syntax can be used for rich text representation.
-  , swaggerOperationDescription :: Maybe Text
+  , _swaggerOperationDescription :: Maybe Text
 
     -- | Additional external documentation for this operation.
-  , swaggerOperationExternalDocs :: Maybe SwaggerExternalDocs
+  , _swaggerOperationExternalDocs :: Maybe SwaggerExternalDocs
 
     -- | Unique string used to identify the operation.
     -- The id MUST be unique among all operations described in the API.
     -- Tools and libraries MAY use the it to uniquely identify an operation,
     -- therefore, it is recommended to follow common programming naming conventions.
-  , swaggerOperationOperationId :: Maybe Text
+  , _swaggerOperationOperationId :: Maybe Text
 
     -- | A list of MIME types the operation can consume.
     -- This overrides the @'swaggerConsumes'@.
     -- @Just []@ MAY be used to clear the global definition.
-  , swaggerOperationConsumes :: Maybe SwaggerMimeList
+  , _swaggerOperationConsumes :: Maybe SwaggerMimeList
 
     -- | A list of MIME types the operation can produce.
     -- This overrides the @'swaggerProduces'@.
     -- @Just []@ MAY be used to clear the global definition.
-  , swaggerOperationProduces :: Maybe SwaggerMimeList
+  , _swaggerOperationProduces :: Maybe SwaggerMimeList
 
     -- | A list of parameters that are applicable for this operation.
     -- If a parameter is already defined at the @'SwaggerPathItem'@,
     -- the new definition will override it, but can never remove it.
     -- The list MUST NOT include duplicated parameters.
     -- A unique parameter is defined by a combination of a name and location.
-  , swaggerOperationParameters :: [SwaggerParameter]
+  , _swaggerOperationParameters :: [SwaggerReferenced SwaggerParameter]
 
     -- | The list of possible responses as they are returned from executing this operation.
-  , swaggerOperationResponses :: SwaggerResponses
+  , _swaggerOperationResponses :: SwaggerResponses
 
     -- | The transfer protocol for the operation.
     -- The value overrides @'swaggerSchemes'@.
-  , swaggerOperationSchemes :: Maybe [SwaggerScheme]
+  , _swaggerOperationSchemes :: Maybe [SwaggerScheme]
 
     -- | Declares this operation to be deprecated.
     -- Usage of the declared operation should be refrained.
     -- Default value is @False@.
-  , swaggerOperationDeprecated :: Bool
+  , _swaggerOperationDeprecated :: Bool
 
     -- | A declaration of which security schemes are applied for this operation.
     -- The list of values describes alternative security schemes that can be used
     -- (that is, there is a logical OR between the security requirements).
     -- This definition overrides any declared top-level security.
     -- To remove a top-level security declaration, @Just []@ can be used.
-  , swaggerOperationSecurity :: [SwaggerSecurityRequirement]
+  , _swaggerOperationSecurity :: [SwaggerSecurityRequirement]
   } deriving (Eq, Show, Generic)
 
 newtype SwaggerMimeList = SwaggerMimeList { getSwaggerMimeList :: [MediaType] }
@@ -260,30 +260,30 @@
 data SwaggerParameter = SwaggerParameter
   { -- | The name of the parameter.
     -- Parameter names are case sensitive.
-    swaggerParameterName :: Text
+    _swaggerParameterName :: Text
 
     -- | A brief description of the parameter.
     -- This could contain examples of use.
     -- GFM syntax can be used for rich text representation.
-  , swaggerParameterDescription :: Maybe Text
+  , _swaggerParameterDescription :: Maybe Text
 
     -- | Determines whether this parameter is mandatory.
     -- If the parameter is in "path", this property is required and its value MUST be true.
     -- Otherwise, the property MAY be included and its default value is @False@.
-  , swaggerParameterRequired :: Bool
+  , _swaggerParameterRequired :: Bool
 
     -- | Parameter schema.
-  , swaggerParameterSchema :: SwaggerParameterSchema
+  , _swaggerParameterSchema :: SwaggerParameterSchema
   } deriving (Eq, Show, Generic)
 
 data SwaggerParameterSchema
-  = SwaggerParameterBody SwaggerSchema
+  = SwaggerParameterBody (SwaggerReferenced SwaggerSchema)
   | SwaggerParameterOther SwaggerParameterOtherSchema
   deriving (Eq, Show)
 
 data SwaggerParameterOtherSchema = SwaggerParameterOtherSchema
   { -- | The location of the parameter.
-    swaggerParameterOtherSchemaIn :: SwaggerParameterLocation
+    _swaggerParameterOtherSchemaIn :: SwaggerParameterLocation
 
     -- | The type of the parameter.
     -- Since the parameter is not located at the request body,
@@ -291,26 +291,26 @@
     -- If type is @'SwaggerParamFile'@, the @consumes@ MUST be either
     -- "multipart/form-data" or " application/x-www-form-urlencoded"
     -- and the parameter MUST be in @'SwaggerParameterFormData'@.
-  , swaggerParameterOtherSchemaType :: SwaggerParameterType
+  , _swaggerParameterOtherSchemaType :: SwaggerParameterType
 
     -- | The extending format for the previously mentioned type.
-  , swaggerParameterOtherSchemaFormat :: Maybe SwaggerFormat
+  , _swaggerParameterOtherSchemaFormat :: Maybe SwaggerFormat
 
     -- | Sets the ability to pass empty-valued parameters.
     -- This is valid only for either @'SwaggerParameterQuery'@ or @'SwaggerParameterFormData'@
     -- and allows you to send a parameter with a name only or an empty value.
     -- Default value is @False@.
-  , swaggerParameterOtherSchemaAllowEmptyValue :: Bool
+  , _swaggerParameterOtherSchemaAllowEmptyValue :: Bool
 
     -- | __Required if type is @'SwaggerParamArray'@__.
     -- Describes the type of items in the array.
-  , swaggerParameterOtherSchemaItems :: Maybe SwaggerItems
+  , _swaggerParameterOtherSchemaItems :: Maybe SwaggerItems
 
     -- | Determines the format of the array if @'SwaggerParamArray'@ is used.
     -- Default value is csv.
-  , swaggerParameterOtherSchemaCollectionFormat :: Maybe SwaggerCollectionFormat
+  , _swaggerParameterOtherSchemaCollectionFormat :: Maybe SwaggerCollectionFormat
 
-  , swaggerParameterOtherSchemaCommon :: SwaggerSchemaCommon
+  , _swaggerParameterOtherSchemaCommon :: SwaggerSchemaCommon
   } deriving (Eq, Show, Generic)
 
 data SwaggerParameterType
@@ -384,32 +384,32 @@
 type SwaggerParamName = Text
 
 data SwaggerSchema = SwaggerSchema
-  { swaggerSchemaType :: SwaggerSchemaType
-  , swaggerSchemaFormat :: Maybe SwaggerFormat
-  , swaggerSchemaTitle :: Maybe Text
-  , swaggerSchemaDescription :: Maybe Text
-  , swaggerSchemaRequired :: [SwaggerParamName]
+  { _swaggerSchemaType :: SwaggerSchemaType
+  , _swaggerSchemaFormat :: Maybe SwaggerFormat
+  , _swaggerSchemaTitle :: Maybe Text
+  , _swaggerSchemaDescription :: Maybe Text
+  , _swaggerSchemaRequired :: [SwaggerParamName]
 
-  , swaggerSchemaItems :: Maybe SwaggerSchemaItems
-  , swaggerSchemaAllOf :: Maybe [SwaggerSchema]
-  , swaggerSchemaProperties :: HashMap Text SwaggerSchema
-  , swaggerSchemaAdditionalProperties :: Maybe SwaggerSchema
+  , _swaggerSchemaItems :: Maybe SwaggerSchemaItems
+  , _swaggerSchemaAllOf :: Maybe [SwaggerSchema]
+  , _swaggerSchemaProperties :: HashMap Text (SwaggerReferenced SwaggerSchema)
+  , _swaggerSchemaAdditionalProperties :: Maybe SwaggerSchema
 
-  , swaggerSchemaDiscriminator :: Maybe Text
-  , swaggerSchemaReadOnly :: Maybe Bool
-  , swaggerSchemaXml :: Maybe SwaggerXml
-  , swaggerSchemaExternalDocs :: Maybe SwaggerExternalDocs
-  , swaggerSchemaExample :: Maybe Value
+  , _swaggerSchemaDiscriminator :: Maybe Text
+  , _swaggerSchemaReadOnly :: Maybe Bool
+  , _swaggerSchemaXml :: Maybe SwaggerXml
+  , _swaggerSchemaExternalDocs :: Maybe SwaggerExternalDocs
+  , _swaggerSchemaExample :: Maybe Value
 
-  , swaggerSchemaMaxProperties :: Maybe Integer
-  , swaggerSchemaMinProperties :: Maybe Integer
+  , _swaggerSchemaMaxProperties :: Maybe Integer
+  , _swaggerSchemaMinProperties :: Maybe Integer
 
-  , swaggerSchemaCommon :: SwaggerSchemaCommon
+  , _swaggerSchemaCommon :: SwaggerSchemaCommon
   } deriving (Eq, Show, Generic)
 
 data SwaggerSchemaItems
-  = SwaggerSchemaItemsObject SwaggerSchema
-  | SwaggerSchemaItemsArray [SwaggerSchema]
+  = SwaggerSchemaItemsObject (SwaggerReferenced SwaggerSchema)
+  | SwaggerSchemaItemsArray [SwaggerReferenced SwaggerSchema]
   deriving (Eq, Show)
 
 data SwaggerSchemaCommon = SwaggerSchemaCommon
@@ -418,20 +418,20 @@
     -- if not supplied by the client in the request.
     -- (Note: "default" has no meaning for required parameters.)
     -- Unlike JSON Schema this value MUST conform to the defined type for this parameter.
-    swaggerSchemaDefault :: Maybe Value
+    _swaggerSchemaDefault :: Maybe Value
 
-  , swaggerSchemaMaximum :: Maybe Integer
-  , swaggerSchemaExclusiveMaximum :: Maybe Bool
-  , swaggerSchemaMinimum :: Maybe Integer
-  , swaggerSchemaExclusiveMinimum :: Maybe Bool
-  , swaggerSchemaMaxLength :: Maybe Integer
-  , swaggerSchemaMinLength :: Maybe Integer
-  , swaggerSchemaPattern :: Maybe Text
-  , swaggerSchemaMaxItems :: Maybe Integer
-  , swaggerSchemaMinItems :: Maybe Integer
-  , swaggerSchemaUniqueItems :: Maybe Bool
-  , swaggerSchemaEnum :: Maybe [Value]
-  , swaggerSchemaMultipleOf :: Maybe Integer
+  , _swaggerSchemaMaximum :: Maybe Integer
+  , _swaggerSchemaExclusiveMaximum :: Maybe Bool
+  , _swaggerSchemaMinimum :: Maybe Integer
+  , _swaggerSchemaExclusiveMinimum :: Maybe Bool
+  , _swaggerSchemaMaxLength :: Maybe Integer
+  , _swaggerSchemaMinLength :: Maybe Integer
+  , _swaggerSchemaPattern :: Maybe Text
+  , _swaggerSchemaMaxItems :: Maybe Integer
+  , _swaggerSchemaMinItems :: Maybe Integer
+  , _swaggerSchemaUniqueItems :: Maybe Bool
+  , _swaggerSchemaEnum :: Maybe [Value]
+  , _swaggerSchemaMultipleOf :: Maybe Integer
   } deriving (Eq, Show, Generic)
 
 data SwaggerXml = SwaggerXml
@@ -440,18 +440,18 @@
     -- When defined alongside type being array (outside the items),
     -- it will affect the wrapping element and only if wrapped is true.
     -- If wrapped is false, it will be ignored.
-    swaggerXmlName :: Maybe Text
+    _swaggerXmlName :: Maybe Text
 
     -- | The URL of the namespace definition.
     -- Value SHOULD be in the form of a URL.
-  , swaggerXmlNamespace :: Maybe Text
+  , _swaggerXmlNamespace :: Maybe Text
 
     -- | The prefix to be used for the name.
-  , swaggerXmlPrefix :: Maybe Text
+  , _swaggerXmlPrefix :: Maybe Text
 
     -- | Declares whether the property definition translates to an attribute instead of an element.
     -- Default value is @False@.
-  , swaggerXmlAttribute :: Bool
+  , _swaggerXmlAttribute :: Bool
 
     -- | MAY be used only for an array definition.
     -- Signifies whether the array is wrapped
@@ -459,25 +459,25 @@
     -- or unwrapped (@\<book/\>\<book/\>@).
     -- Default value is @False@.
     -- The definition takes effect only when defined alongside type being array (outside the items).
-  , swaggerXmlWrapped :: Bool
-  } deriving (Eq, Show)
+  , _swaggerXmlWrapped :: Bool
+  } deriving (Eq, Show, Generic)
 
 data SwaggerItems = SwaggerItems
   { -- | The internal type of the array.
-    swaggerItemsType :: SwaggerItemsType
+    _swaggerItemsType :: SwaggerItemsType
 
     -- | The extending format for the previously mentioned type.
-  , swaggerItemsFormat :: SwaggerFormat
+  , _swaggerItemsFormat :: Maybe SwaggerFormat
 
     -- | __Required if type is @'SwaggerItemsArray'@.__
     -- Describes the type of items in the array.
-  , swaggerItemsItems :: SwaggerItems
+  , _swaggerItemsItems :: Maybe SwaggerItems
 
     -- | Determines the format of the array if type array is used.
     -- Default value is @'SwaggerItemsCollectionCSV'@.
-  , swaggerItemsCollectionFormat :: SwaggerItemsCollectionFormat
+  , _swaggerItemsCollectionFormat :: Maybe SwaggerItemsCollectionFormat
 
-  , swaggerItemsCommon :: SwaggerSchemaCommon
+  , _swaggerItemsCommon :: SwaggerSchemaCommon
   } deriving (Eq, Show, Generic)
 
 -- | A container for the expected responses of an operation.
@@ -488,11 +488,11 @@
 data SwaggerResponses = SwaggerResponses
   { -- | The documentation of responses other than the ones declared for specific HTTP response codes.
     -- It can be used to cover undeclared responses.
-    swaggerResponsesDefault :: Maybe SwaggerResponse
+   _swaggerResponsesDefault :: Maybe (SwaggerReferenced SwaggerResponse)
 
     -- | Any HTTP status code can be used as the property name (one property per HTTP status code).
     -- Describes the expected response for those HTTP status codes.
-  , swaggerResponsesResponses :: HashMap HttpStatusCode SwaggerResponse
+  , _swaggerResponsesResponses :: HashMap HttpStatusCode (SwaggerReferenced SwaggerResponse)
   } deriving (Eq, Show, Generic)
 
 type HttpStatusCode = Int
@@ -501,43 +501,43 @@
 data SwaggerResponse = SwaggerResponse
   { -- | A short description of the response.
     -- GFM syntax can be used for rich text representation.
-    swaggerResponseDescription :: Text
+    _swaggerResponseDescription :: Text
 
     -- | A definition of the response structure.
     -- It can be a primitive, an array or an object.
     -- If this field does not exist, it means no content is returned as part of the response.
     -- As an extension to the Schema Object, its root type value may also be "file".
     -- This SHOULD be accompanied by a relevant produces mime-type.
-  , swaggerResponseSchema :: Maybe SwaggerSchema
+  , _swaggerResponseSchema :: Maybe (SwaggerReferenced SwaggerSchema)
 
     -- | A list of headers that are sent with the response.
-  , swaggerResponseHeaders :: HashMap HeaderName SwaggerHeader
+  , _swaggerResponseHeaders :: HashMap HeaderName SwaggerHeader
 
     -- | An example of the response message.
-  , swaggerResponseExamples :: Maybe SwaggerExample
+  , _swaggerResponseExamples :: Maybe SwaggerExample
   } deriving (Eq, Show, Generic)
 
 type HeaderName = Text
 
 data SwaggerHeader = SwaggerHeader
   { -- | A short description of the header.
-    swaggerHeaderDescription :: Maybe String
+    _swaggerHeaderDescription :: Maybe Text
 
     -- | The type of the object.
-  , swaggerHeaderType :: SwaggerItemsType
+  , _swaggerHeaderType :: SwaggerItemsType
 
     -- | The extending format for the previously mentioned type. See Data Type Formats for further details.
-  , swaggerHeaderFormat :: Maybe SwaggerFormat
+  , _swaggerHeaderFormat :: Maybe SwaggerFormat
 
     -- | __Required if type is @'SwaggerItemsArray'@__.
     -- Describes the type of items in the array.
-  , swaggerHeaderItems :: SwaggerItems
+  , _swaggerHeaderItems :: Maybe SwaggerItems
 
     -- | Determines the format of the array if type array is used.
     -- Default value is @'SwaggerItemsCollectionCSV'@.
-  , swaggerHeaderCollectionFormat :: SwaggerItemsCollectionFormat
+  , _swaggerHeaderCollectionFormat :: Maybe SwaggerItemsCollectionFormat
 
-  , swaggerHeaderCommon :: SwaggerSchemaCommon
+  , _swaggerHeaderCommon :: SwaggerSchemaCommon
   } deriving (Eq, Show, Generic)
 
 data SwaggerExample = SwaggerExample { getSwaggerExample :: Map MediaType Value }
@@ -551,10 +551,10 @@
 
 data SwaggerApiKeyParams = SwaggerApiKeyParams
   { -- | The name of the header or query parameter to be used.
-    swaggerApiKeyName :: Text
+    _swaggerApiKeyName :: Text
 
     -- | The location of the API key.
-  , swaggerApiKeyIn :: SwaggerApiKeyLocation
+  , _swaggerApiKeyIn :: SwaggerApiKeyLocation
   } deriving (Eq, Show)
 
 -- | The authorization URL to be used for OAuth2 flow. This SHOULD be in the form of a URL.
@@ -572,10 +572,10 @@
 
 data SwaggerOAuth2Params = SwaggerOAuth2Params
   { -- | The flow used by the OAuth2 security scheme.
-    swaggerOAuth2Flow :: SwaggerOAuth2Flow
+    _swaggerOAuth2Flow :: SwaggerOAuth2Flow
 
     -- | The available scopes for the OAuth2 security scheme.
-  , swaggerOAuth2Scopes :: HashMap Text Text
+  , _swaggerOAuth2Scopes :: HashMap Text Text
   } deriving (Eq, Show, Generic)
 
 data SwaggerSecuritySchemeType
@@ -586,10 +586,10 @@
 
 data SwaggerSecurityScheme = SwaggerSecurityScheme
   { -- | The type of the security scheme.
-    swaggerSecuritySchemeType :: SwaggerSecuritySchemeType
+    _swaggerSecuritySchemeType :: SwaggerSecuritySchemeType
 
     -- | A short description for security scheme.
-  , swaggerSecuritySchemeDescription :: Maybe Text
+  , _swaggerSecuritySchemeDescription :: Maybe Text
   } deriving (Eq, Show, Generic)
 
 -- | Lists the required security schemes to execute this operation.
@@ -603,26 +603,36 @@
 -- It is not mandatory to have a @SwaggerTag@ per tag used there.
 data SwaggerTag = SwaggerTag
   { -- | The name of the tag.
-    swaggerTagName :: Text
+    _swaggerTagName :: Text
 
     -- | A short description for the tag.
     -- GFM syntax can be used for rich text representation.
-  , swaggerTagDescription :: Maybe Text
+  , _swaggerTagDescription :: Maybe Text
 
     -- | Additional external documentation for this tag.
-  , swaggerTagExternalDocs :: Maybe SwaggerExternalDocs
+  , _swaggerTagExternalDocs :: Maybe SwaggerExternalDocs
   } deriving (Eq, Show)
 
 -- | Allows referencing an external resource for extended documentation.
 data SwaggerExternalDocs = SwaggerExternalDocs
   { -- | A short description of the target documentation.
     -- GFM syntax can be used for rich text representation.
-    swaggerExternalDocsDescription :: Maybe Text
+    _swaggerExternalDocsDescription :: Maybe Text
 
     -- | The URL for the target documentation.
-  , swaggerExternalDocsUrl :: URL
+  , _swaggerExternalDocsUrl :: URL
   } deriving (Eq, Show, Generic)
 
+-- | A simple object to allow referencing other definitions in the specification.
+-- It can be used to reference parameters and responses that are defined at the top level for reuse.
+newtype SwaggerReference = SwaggerReference { getSwaggerReference :: Text }
+  deriving (Eq, Show)
+
+data SwaggerReferenced a
+  = SwaggerRef SwaggerReference
+  | SwaggerInline a
+  deriving (Eq, Show)
+
 newtype URL = URL { getUrl :: Text } deriving (Eq, Show, ToJSON, FromJSON)
 
 -- =======================================================================
@@ -712,6 +722,15 @@
   swaggerMempty = HashMap.empty
   swaggerMappend = HashMap.unionWith mappend
 
+instance SwaggerMonoid (HashMap Text (SwaggerReferenced SwaggerSchema)) where
+  swaggerMempty = HashMap.empty
+  swaggerMappend = HashMap.unionWith swaggerMappend
+
+instance Monoid a => SwaggerMonoid (SwaggerReferenced a) where
+  swaggerMempty = SwaggerInline mempty
+  swaggerMappend (SwaggerInline x) (SwaggerInline y) = SwaggerInline (x <> y)
+  swaggerMappend _ y = y
+
 instance SwaggerMonoid (HashMap Text SwaggerParameter) where
   swaggerMempty = HashMap.empty
   swaggerMappend = HashMap.unionWith mappend
@@ -732,7 +751,7 @@
   swaggerMempty = HashMap.empty
   swaggerMappend = flip HashMap.union
 
-instance SwaggerMonoid (HashMap HttpStatusCode SwaggerResponse) where
+instance SwaggerMonoid (HashMap HttpStatusCode (SwaggerReferenced SwaggerResponse)) where
   swaggerMempty = HashMap.empty
   swaggerMappend = flip HashMap.union
 
@@ -761,11 +780,11 @@
 deriveJSONDefault ''SwaggerScheme
 deriveJSON' ''SwaggerTag
 deriveJSON' ''SwaggerExternalDocs
-deriveJSON' ''SwaggerXml
 
 deriveToJSON' ''SwaggerOperation
 deriveToJSON' ''SwaggerResponse
 deriveToJSON' ''SwaggerPathItem
+deriveToJSON' ''SwaggerXml
 
 -- =======================================================================
 -- Manual ToJSON instances
@@ -833,7 +852,7 @@
   toJSON = genericToJSONWithSub "schema" (jsonPrefix "swaggerParameter")
 
 instance ToJSON SwaggerParameterSchema where
-  toJSON (SwaggerParameterBody s) = toJSON s <+> object [ "in" .= ("body" :: Text) ]
+  toJSON (SwaggerParameterBody s) = object [ "in" .= ("body" :: Text), "schema" .= s ]
   toJSON (SwaggerParameterOther s) = toJSON s
 
 instance ToJSON SwaggerParameterOtherSchema where
@@ -849,6 +868,13 @@
 instance ToJSON SwaggerExample where
   toJSON = toJSON . Map.mapKeys show . getSwaggerExample
 
+instance ToJSON SwaggerReference where
+  toJSON (SwaggerReference ref) = object [ "$ref" .= ref ]
+
+instance ToJSON a => ToJSON (SwaggerReferenced a) where
+  toJSON (SwaggerRef ref) = toJSON ref
+  toJSON (SwaggerInline x) = toJSON x
+
 -- =======================================================================
 -- Manual FromJSON instances
 -- =======================================================================
@@ -912,10 +938,10 @@
 instance FromJSON SwaggerHost where
   parseJSON (String s) =
     case fromInteger <$> readMaybe portStr of
-      Nothing | not (null portStr) -> empty
+      Nothing | not (null portStr) -> fail $ "Invalid port `" ++ portStr ++ "'"
       mport -> pure $ SwaggerHost host mport
     where
-      (hostText, portText) = Text.breakOnEnd ":" s
+      (hostText, portText) = Text.breakOn ":" s
       [host, portStr] = map Text.unpack [hostText, portText]
   parseJSON _ = empty
 
@@ -933,7 +959,9 @@
   parseJSON json@(Object o) = do
     (i :: Text) <- o .: "in"
     case i of
-      "body" -> SwaggerParameterBody <$> parseJSON json
+      "body" -> do
+        schema <- o .: "schema"
+        SwaggerParameterBody <$> parseJSON schema
       _ -> SwaggerParameterOther <$> parseJSON json
   parseJSON _ = empty
 
@@ -969,4 +997,17 @@
 instance FromJSON SwaggerPathItem where
   parseJSON = genericParseJSON (jsonPrefix "swaggerPathItem")
     `withDefaults` [ "parameters" .= ([] :: [SwaggerParameter]) ]
+
+instance FromJSON SwaggerReference where
+  parseJSON (Object o) = SwaggerReference <$> o .: "$ref"
+  parseJSON _ = empty
+
+instance FromJSON a => FromJSON (SwaggerReferenced a) where
+  parseJSON json
+      = SwaggerRef    <$> parseJSON json
+    <|> SwaggerInline <$> parseJSON json
+
+instance FromJSON SwaggerXml where
+  parseJSON = genericParseJSON (jsonPrefix "swaggerXml")
+    `withDefaults` [ "attribute" .= False, "wrapped" .= False ]
 
diff --git a/src/Data/Swagger/Internal/Utils.hs b/src/Data/Swagger/Internal/Utils.hs
--- a/src/Data/Swagger/Internal/Utils.hs
+++ b/src/Data/Swagger/Internal/Utils.hs
@@ -32,7 +32,7 @@
 
 jsonPrefix :: String -> Options
 jsonPrefix prefix = defaultOptions
-  { fieldLabelModifier      = modifier
+  { fieldLabelModifier      = modifier . drop 1
   , constructorTagModifier  = modifier
   , sumEncoding             = ObjectWithSingleField
   }
diff --git a/src/Data/Swagger/Lens.hs b/src/Data/Swagger/Lens.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Swagger/Lens.hs
@@ -0,0 +1,107 @@
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE FunctionalDependencies #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE TemplateHaskell #-}
+module Data.Swagger.Lens where
+
+import Control.Lens
+import Control.Lens.TH
+import Data.Aeson (Value)
+import Data.Swagger.Internal
+import Data.Text (Text)
+
+-- =======================================================================
+-- TH derived lenses
+-- =======================================================================
+
+makeLenses ''Swagger
+makeLenses ''SwaggerHost
+makeLenses ''SwaggerInfo
+makeLenses ''SwaggerContact
+makeLenses ''SwaggerLicense
+makeLenses ''SwaggerPaths
+makeLenses ''SwaggerPathItem
+makeLenses ''SwaggerTag
+makeLenses ''SwaggerOperation
+makeLenses ''SwaggerParameter
+makePrisms ''SwaggerParameterSchema
+makeLenses ''SwaggerParameterOtherSchema
+makeLenses ''SwaggerItems
+makeLenses ''SwaggerHeader
+makeLenses ''SwaggerSchema
+makePrisms ''SwaggerSchemaItems
+makeLenses ''SwaggerSchemaCommon
+makeLenses ''SwaggerXml
+makeLenses ''SwaggerResponses
+makeLenses ''SwaggerResponse
+makeLenses ''SwaggerSecurityScheme
+makePrisms ''SwaggerSecuritySchemeType
+makeLenses ''SwaggerApiKeyParams
+makeLenses ''SwaggerOAuth2Params
+makeLenses ''SwaggerExternalDocs
+
+-- =======================================================================
+-- Helper classy lenses
+-- =======================================================================
+
+class HasDescription s d | s -> d where
+  description :: Lens' s d
+
+instance HasDescription SwaggerResponse       Text where description = swaggerResponseDescription
+instance HasDescription SwaggerInfo           (Maybe Text) where description = swaggerInfoDescription
+instance HasDescription SwaggerTag            (Maybe Text) where description = swaggerTagDescription
+instance HasDescription SwaggerOperation      (Maybe Text) where description = swaggerOperationDescription
+instance HasDescription SwaggerParameter      (Maybe Text) where description = swaggerParameterDescription
+instance HasDescription SwaggerHeader         (Maybe Text) where description = swaggerHeaderDescription
+instance HasDescription SwaggerSchema         (Maybe Text) where description = swaggerSchemaDescription
+instance HasDescription SwaggerSecurityScheme (Maybe Text) where description = swaggerSecuritySchemeDescription
+instance HasDescription SwaggerExternalDocs   (Maybe Text) where description = swaggerExternalDocsDescription
+
+class HasSwaggerSchemaCommon s where
+  schemaCommon :: Lens' s SwaggerSchemaCommon
+
+instance HasSwaggerSchemaCommon SwaggerSchema where schemaCommon = swaggerSchemaCommon
+instance HasSwaggerSchemaCommon SwaggerParameterOtherSchema where schemaCommon = swaggerParameterOtherSchemaCommon
+instance HasSwaggerSchemaCommon SwaggerItems where schemaCommon = swaggerItemsCommon
+instance HasSwaggerSchemaCommon SwaggerHeader where schemaCommon = swaggerHeaderCommon
+instance HasSwaggerSchemaCommon SwaggerSchemaCommon where schemaCommon = id
+
+schemaDefault :: HasSwaggerSchemaCommon s => Lens' s (Maybe Value)
+schemaDefault = schemaCommon.swaggerSchemaDefault
+
+schemaMaximum :: HasSwaggerSchemaCommon s => Lens' s (Maybe Integer)
+schemaMaximum = schemaCommon.swaggerSchemaMaximum
+
+schemaExclusiveMaximum :: HasSwaggerSchemaCommon s => Lens' s (Maybe Bool)
+schemaExclusiveMaximum = schemaCommon.swaggerSchemaExclusiveMaximum
+
+schemaMinimum :: HasSwaggerSchemaCommon s => Lens' s (Maybe Integer)
+schemaMinimum = schemaCommon.swaggerSchemaMinimum
+
+schemaExclusiveMinimum :: HasSwaggerSchemaCommon s => Lens' s (Maybe Bool)
+schemaExclusiveMinimum = schemaCommon.swaggerSchemaExclusiveMinimum
+
+schemaMaxLength :: HasSwaggerSchemaCommon s => Lens' s (Maybe Integer)
+schemaMaxLength = schemaCommon.swaggerSchemaMaxLength
+
+schemaMinLength :: HasSwaggerSchemaCommon s => Lens' s (Maybe Integer)
+schemaMinLength = schemaCommon.swaggerSchemaMinLength
+
+schemaPattern :: HasSwaggerSchemaCommon s => Lens' s (Maybe Text)
+schemaPattern = schemaCommon.swaggerSchemaPattern
+
+schemaMaxItems :: HasSwaggerSchemaCommon s => Lens' s (Maybe Integer)
+schemaMaxItems = schemaCommon.swaggerSchemaMaxItems
+
+schemaMinItems :: HasSwaggerSchemaCommon s => Lens' s (Maybe Integer)
+schemaMinItems = schemaCommon.swaggerSchemaMinItems
+
+schemaUniqueItems :: HasSwaggerSchemaCommon s => Lens' s (Maybe Bool)
+schemaUniqueItems = schemaCommon.swaggerSchemaUniqueItems
+
+schemaEnum :: HasSwaggerSchemaCommon s => Lens' s (Maybe [Value])
+schemaEnum = schemaCommon.swaggerSchemaEnum
+
+schemaMultipleOf :: HasSwaggerSchemaCommon s => Lens' s (Maybe Integer)
+schemaMultipleOf = schemaCommon.swaggerSchemaMultipleOf
+
diff --git a/swagger2.cabal b/swagger2.cabal
--- a/swagger2.cabal
+++ b/swagger2.cabal
@@ -1,5 +1,5 @@
 name:                swagger2
-version:             0.1
+version:             0.2
 synopsis:            Swagger 2.0 data model
 description:         Please see README.md
 homepage:            https://github.com/GetShopTV/swagger2
@@ -12,12 +12,16 @@
 build-type:          Simple
 extra-source-files:
     README.md
+  , CHANGELOG.md
 cabal-version:       >=1.10
 
 library
   hs-source-dirs:      src
   exposed-modules:
     Data.Swagger
+    Data.Swagger.Lens
+
+    -- internal modules
     Data.Swagger.Internal
     Data.Swagger.Internal.Utils
   build-depends:       base == 4.*
@@ -29,6 +33,7 @@
                      , template-haskell
                      , text
                      , unordered-containers
+                     , lens
   default-language:    Haskell2010
 
 test-suite spec
diff --git a/test/Data/SwaggerSpec.hs b/test/Data/SwaggerSpec.hs
--- a/test/Data/SwaggerSpec.hs
+++ b/test/Data/SwaggerSpec.hs
@@ -1,612 +1,1659 @@
 {-# LANGUAGE OverloadedLists #-}
 {-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE QuasiQuotes #-}
-module Data.SwaggerSpec where
-
-import Data.Aeson
-import Data.Aeson.QQ
-import qualified Data.Foldable as F
-import Data.HashMap.Strict (HashMap)
-import qualified Data.HashMap.Strict as HashMap
-import Data.Maybe
-import Data.Monoid
-import qualified Data.Vector as Vector
-import Data.Text (Text)
-
-import Data.Swagger
-
-import Test.Hspec
-
-isSubJSON :: Value -> Value -> Bool
-isSubJSON Null _ = True
-isSubJSON (Object x) (Object y) = HashMap.keys x == HashMap.keys i && F.and i
-  where
-    i = HashMap.intersectionWith isSubJSON x y
-isSubJSON (Array xs) (Array ys) = Vector.length xs == Vector.length ys && F.and (Vector.zipWith isSubJSON xs ys)
-isSubJSON x y = x == y
-
-(<~>) :: (Eq a, Show a, ToJSON a, FromJSON a) => a -> Value -> Spec
-x <~> json = do
-  it "encodes correctly (probably with extra properties)" $ do
-    toJSON x `shouldSatisfy` (json `isSubJSON`)
-  it "decodes correctly" $ do
-    fromJSON json `shouldBe` Success x
-
-(<=>) :: (Eq a, Show a, ToJSON a, FromJSON a) => a -> Value -> Spec
-x <=> json = do
-  it "encodes correctly" $ do
-    toJSON x `shouldBe` json
-  it "decodes correctly" $ do
-    fromJSON json `shouldBe` Success x
-
-spec :: Spec
-spec = do
-  describe "License Object" $ licenseExample <=> licenseExampleJSON
-  describe "Contact Object" $ contactExample <=> contactExampleJSON
-  describe "Info Object" $ infoExample <=> infoExampleJSON
-  describe "Operation Object" $ operationExample <~> operationExampleJSON
-  describe "Schema Object" $ do
-    context "Primitive Sample" $ schemaPrimitiveExample <~> schemaPrimitiveExampleJSON
-    context "Simple Model" $ schemaSimpleModelExample <~> schemaSimpleModelExampleJSON
-    context "Model with Map/Dictionary Properties" $ schemaModelDictExample <~> schemaModelDictExampleJSON
-    context "Model with Example" $ schemaWithExampleExample <~> schemaWithExampleExampleJSON
-  describe "Definitions Object" $ definitionsExample <~> definitionsExampleJSON
-  describe "Parameters Definition Object" $ parametersDefinitionExample <~> parametersDefinitionExampleJSON
-  describe "Responses Definition Object" $ responsesDefinitionExample <~> responsesDefinitionExampleJSON
-  describe "Security Definitions Object" $ securityDefinitionsExample <~> securityDefinitionsExampleJSON
-  describe "Swagger Object" $ swaggerExample <~> swaggerExampleJSON
-
-main :: IO ()
-main = hspec spec
-
--- =======================================================================
--- Info object
--- =======================================================================
-
-infoExample :: SwaggerInfo
-infoExample = SwaggerInfo
-  { swaggerInfoTitle = "Swagger Sample App"
-  , swaggerInfoDescription = Just "This is a sample server Petstore server."
-  , swaggerInfoTermsOfService = Just "http://swagger.io/terms/"
-  , swaggerInfoContact = Just contactExample
-  , swaggerInfoLicense = Just licenseExample
-  , swaggerInfoVersion = "1.0.1" }
-  where
-    license = SwaggerLicense
-      { swaggerLicenseName = "Apache 2.0"
-      , swaggerLicenseUrl = Just (URL "http://www.apache.org/licenses/LICENSE-2.0.html") }
-
-infoExampleJSON :: Value
-infoExampleJSON = [aesonQQ|
-{
-  "title": "Swagger Sample App",
-  "description": "This is a sample server Petstore server.",
-  "termsOfService": "http://swagger.io/terms/",
-  "contact": {
-    "name": "API Support",
-    "url": "http://www.swagger.io/support",
-    "email": "support@swagger.io"
-  },
-  "license": {
-    "name": "Apache 2.0",
-    "url": "http://www.apache.org/licenses/LICENSE-2.0.html"
-  },
-  "version": "1.0.1"
-}
-|]
-
--- =======================================================================
--- Contact object
--- =======================================================================
-
-contactExample :: SwaggerContact
-contactExample = SwaggerContact
-  { swaggerContactName = Just "API Support"
-  , swaggerContactUrl = Just (URL "http://www.swagger.io/support")
-  , swaggerContactEmail = Just "support@swagger.io" }
-
-contactExampleJSON :: Value
-contactExampleJSON = [aesonQQ|
-{
-  "name": "API Support",
-  "url": "http://www.swagger.io/support",
-  "email": "support@swagger.io"
-}
-|]
-
--- =======================================================================
--- License object
--- =======================================================================
-
-licenseExample :: SwaggerLicense
-licenseExample = SwaggerLicense
-  { swaggerLicenseName = "Apache 2.0"
-  , swaggerLicenseUrl = Just (URL "http://www.apache.org/licenses/LICENSE-2.0.html") }
-
-licenseExampleJSON :: Value
-licenseExampleJSON = [aesonQQ|
-{
-  "name": "Apache 2.0",
-  "url": "http://www.apache.org/licenses/LICENSE-2.0.html"
-}
-|]
-
-
--- =======================================================================
--- Operation object
--- =======================================================================
-
-operationExample :: SwaggerOperation
-operationExample = mempty
-  { swaggerOperationTags = ["pet"]
-  , swaggerOperationSummary = Just "Updates a pet in the store with form data"
-  , swaggerOperationDescription = Just ""
-  , swaggerOperationOperationId = Just "updatePetWithForm"
-  , swaggerOperationConsumes = Just (SwaggerMimeList ["application/x-www-form-urlencoded"])
-  , swaggerOperationProduces = Just (SwaggerMimeList ["application/json", "application/xml"])
-  , swaggerOperationParameters = params
-  , swaggerOperationResponses = responses
-  , swaggerOperationSecurity = security
-  }
-  where
-    security = [SwaggerSecurityRequirement [("petstore_auth", ["write:pets", "read:pets"])]]
-
-    responses = mempty
-      { swaggerResponsesResponses =
-          [ (200, mempty { swaggerResponseDescription = "Pet updated." })
-          , (405, mempty { swaggerResponseDescription = "Invalid input" }) ] }
-
-    params =
-      [ SwaggerParameter
-          { swaggerParameterName = "petId"
-          , swaggerParameterDescription = Just "ID of pet that needs to be updated"
-          , swaggerParameterRequired = True
-          , swaggerParameterSchema = SwaggerParameterOther (stringSchema SwaggerParameterPath) }
-      , SwaggerParameter
-          { swaggerParameterName = "name"
-          , swaggerParameterDescription = Just "Updated name of the pet"
-          , swaggerParameterRequired = False
-          , swaggerParameterSchema = SwaggerParameterOther (stringSchema SwaggerParameterFormData) }
-      , SwaggerParameter
-          { swaggerParameterName = "status"
-          , swaggerParameterDescription = Just "Updated status of the pet"
-          , swaggerParameterRequired = False
-          , swaggerParameterSchema = SwaggerParameterOther (stringSchema SwaggerParameterFormData) }
-      ]
-
-    stringSchema i = mempty
-      { swaggerParameterOtherSchemaIn = i
-      , swaggerParameterOtherSchemaType = SwaggerParamString
-      }
-
-operationExampleJSON :: Value
-operationExampleJSON = [aesonQQ|
-{
-  "tags": [
-    "pet"
-  ],
-  "summary": "Updates a pet in the store with form data",
-  "description": "",
-  "operationId": "updatePetWithForm",
-  "consumes": [
-    "application/x-www-form-urlencoded"
-  ],
-  "produces": [
-    "application/json",
-    "application/xml"
-  ],
-  "parameters": [
-    {
-      "name": "petId",
-      "in": "path",
-      "description": "ID of pet that needs to be updated",
-      "required": true,
-      "type": "string"
-    },
-    {
-      "name": "name",
-      "in": "formData",
-      "description": "Updated name of the pet",
-      "required": false,
-      "type": "string"
-    },
-    {
-      "name": "status",
-      "in": "formData",
-      "description": "Updated status of the pet",
-      "required": false,
-      "type": "string"
-    }
-  ],
-  "responses": {
-    "200": {
-      "description": "Pet updated."
-    },
-    "405": {
-      "description": "Invalid input"
-    }
-  },
-  "security": [
-    {
-      "petstore_auth": [
-        "write:pets",
-        "read:pets"
-      ]
-    }
-  ]
-}
-|]
-
--- =======================================================================
--- Schema object
--- =======================================================================
-
-schemaPrimitiveExample :: SwaggerSchema
-schemaPrimitiveExample = mempty
-  { swaggerSchemaType = SwaggerSchemaString
-  , swaggerSchemaFormat = Just "email"
-  }
-
-schemaPrimitiveExampleJSON :: Value
-schemaPrimitiveExampleJSON = [aesonQQ|
-{
-    "type": "string",
-    "format": "email"
-}
-|]
-
-schemaSimpleModelExample :: SwaggerSchema
-schemaSimpleModelExample = mempty
-  { swaggerSchemaType = SwaggerSchemaObject
-  , swaggerSchemaRequired = [ "name" ]
-  , swaggerSchemaProperties =
-      [ ("name", mempty
-            { swaggerSchemaType = SwaggerSchemaString } )
-      , ("age", mempty
-            { swaggerSchemaType = SwaggerSchemaInteger
-            , swaggerSchemaFormat = Just "int32"
-            , swaggerSchemaCommon = mempty
-                { swaggerSchemaMinimum = Just 0 } } ) ] }
-
-schemaSimpleModelExampleJSON :: Value
-schemaSimpleModelExampleJSON = [aesonQQ|
-{
-  "type": "object",
-  "required": [
-    "name"
-  ],
-  "properties": {
-    "name": {
-      "type": "string"
-    },
-    "age": {
-      "type": "integer",
-      "format": "int32",
-      "minimum": 0
-    }
-  }
-}
-|]
-
-schemaModelDictExample :: SwaggerSchema
-schemaModelDictExample = mempty
-  { swaggerSchemaType = SwaggerSchemaObject
-  , swaggerSchemaAdditionalProperties = Just mempty
-      { swaggerSchemaType = SwaggerSchemaString } }
-
-schemaModelDictExampleJSON :: Value
-schemaModelDictExampleJSON = [aesonQQ|
-{
-  "type": "object",
-  "additionalProperties": {
-    "type": "string"
-  }
-}
-|]
-
-schemaWithExampleExample :: SwaggerSchema
-schemaWithExampleExample = mempty
-  { swaggerSchemaType = SwaggerSchemaObject
-  , swaggerSchemaProperties =
-      [ ("id", mempty
-            { swaggerSchemaType   = SwaggerSchemaInteger
-            , swaggerSchemaFormat = Just "int64" })
-      , ("name", mempty
-            { swaggerSchemaType = SwaggerSchemaString }) ]
-  , swaggerSchemaRequired = [ "name" ]
-  , swaggerSchemaExample = Just [aesonQQ|
-      {
-        "name": "Puma",
-        "id": 1
-      }
-    |] }
-
-schemaWithExampleExampleJSON :: Value
-schemaWithExampleExampleJSON = [aesonQQ|
-{
-  "type": "object",
-  "properties": {
-    "id": {
-      "type": "integer",
-      "format": "int64"
-    },
-    "name": {
-      "type": "string"
-    }
-  },
-  "required": [
-    "name"
-  ],
-  "example": {
-    "name": "Puma",
-    "id": 1
-  }
-}
-|]
-
--- =======================================================================
--- Definitions object
--- =======================================================================
-
-definitionsExample :: HashMap Text SwaggerSchema
-definitionsExample =
-  [ ("Category", mempty
-      { swaggerSchemaType = SwaggerSchemaObject
-      , swaggerSchemaProperties =
-          [ ("id", mempty
-              { swaggerSchemaType = SwaggerSchemaInteger
-              , swaggerSchemaFormat = Just "int64" })
-          , ("name", mempty
-              { swaggerSchemaType = SwaggerSchemaString }) ] })
-  , ("Tag", mempty
-      { swaggerSchemaType = SwaggerSchemaObject
-      , swaggerSchemaProperties =
-          [ ("id", mempty
-              { swaggerSchemaType = SwaggerSchemaInteger
-              , swaggerSchemaFormat = Just "int64" })
-          , ("name", mempty
-              { swaggerSchemaType = SwaggerSchemaString }) ] }) ]
-
-definitionsExampleJSON :: Value
-definitionsExampleJSON = [aesonQQ|
-{
-  "Category": {
-    "type": "object",
-    "properties": {
-      "id": {
-        "type": "integer",
-        "format": "int64"
-      },
-      "name": {
-        "type": "string"
-      }
-    }
-  },
-  "Tag": {
-    "type": "object",
-    "properties": {
-      "id": {
-        "type": "integer",
-        "format": "int64"
-      },
-      "name": {
-        "type": "string"
-      }
-    }
-  }
-}
-|]
-
--- =======================================================================
--- Parameters Definition object
--- =======================================================================
-
-parametersDefinitionExample :: HashMap Text SwaggerParameter
-parametersDefinitionExample =
-  [ ("skipParam", mempty
-      { swaggerParameterName = "skip"
-      , swaggerParameterDescription = Just "number of items to skip"
-      , swaggerParameterRequired = True
-      , swaggerParameterSchema = SwaggerParameterOther mempty
-          { swaggerParameterOtherSchemaIn = SwaggerParameterQuery
-          , swaggerParameterOtherSchemaType = SwaggerParamInteger
-          , swaggerParameterOtherSchemaFormat = Just "int32" } })
-  , ("limitParam", mempty
-      { swaggerParameterName = "limit"
-      , swaggerParameterDescription = Just "max records to return"
-      , swaggerParameterRequired = True
-      , swaggerParameterSchema = SwaggerParameterOther mempty
-          { swaggerParameterOtherSchemaIn = SwaggerParameterQuery
-          , swaggerParameterOtherSchemaType = SwaggerParamInteger
-          , swaggerParameterOtherSchemaFormat = Just "int32" } }) ]
-
-parametersDefinitionExampleJSON :: Value
-parametersDefinitionExampleJSON = [aesonQQ|
-{
-  "skipParam": {
-    "name": "skip",
-    "in": "query",
-    "description": "number of items to skip",
-    "required": true,
-    "type": "integer",
-    "format": "int32"
-  },
-  "limitParam": {
-    "name": "limit",
-    "in": "query",
-    "description": "max records to return",
-    "required": true,
-    "type": "integer",
-    "format": "int32"
-  }
-}
-|]
-
--- =======================================================================
--- Responses Definition object
--- =======================================================================
-
-responsesDefinitionExample :: HashMap Text SwaggerResponse
-responsesDefinitionExample =
-  [ ("NotFound", mempty { swaggerResponseDescription = "Entity not found." })
-  , ("IllegalInput", mempty { swaggerResponseDescription = "Illegal input for operation." }) ]
-
-responsesDefinitionExampleJSON :: Value
-responsesDefinitionExampleJSON = [aesonQQ|
-{
-  "NotFound": {
-    "description": "Entity not found."
-  },
-  "IllegalInput": {
-    "description": "Illegal input for operation."
-  }
-}
-|]
-
--- =======================================================================
--- Responses Definition object
--- =======================================================================
-
-securityDefinitionsExample :: HashMap Text SwaggerSecurityScheme
-securityDefinitionsExample =
-  [ ("api_key", SwaggerSecurityScheme
-      { swaggerSecuritySchemeType = SwaggerSecuritySchemeApiKey (SwaggerApiKeyParams "api_key" SwaggerApiKeyHeader)
-      , swaggerSecuritySchemeDescription = Nothing })
-  , ("petstore_auth", SwaggerSecurityScheme
-      { swaggerSecuritySchemeType = SwaggerSecuritySchemeOAuth2 (SwaggerOAuth2Params
-          { swaggerOAuth2Flow = SwaggerOAuth2Implicit "http://swagger.io/api/oauth/dialog"
-          , swaggerOAuth2Scopes =
-              [ ("write:pets",  "modify pets in your account")
-              , ("read:pets", "read your pets") ] } )
-      , swaggerSecuritySchemeDescription = Nothing }) ]
-
-securityDefinitionsExampleJSON :: Value
-securityDefinitionsExampleJSON = [aesonQQ|
-{
-  "api_key": {
-    "type": "apiKey",
-    "name": "api_key",
-    "in": "header"
-  },
-  "petstore_auth": {
-    "type": "oauth2",
-    "authorizationUrl": "http://swagger.io/api/oauth/dialog",
-    "flow": "implicit",
-    "scopes": {
-      "write:pets": "modify pets in your account",
-      "read:pets": "read your pets"
-    }
-  }
-}
-|]
-
--- =======================================================================
--- Swagger object
--- =======================================================================
-
-swaggerExample :: Swagger
-swaggerExample = mempty
-  { swaggerBasePath = Just "/"
-  , swaggerSchemes = Just [Http]
-  , swaggerInfo = mempty
-      { swaggerInfoVersion = "1.0"
-      , swaggerInfoTitle = "Todo API"
-      , swaggerInfoLicense = Just SwaggerLicense
-          { swaggerLicenseName = "MIT"
-          , swaggerLicenseUrl = Just (URL "http://mit.com") }
-      , swaggerInfoDescription = Just "This is a an API that tests servant-swagger support for a Todo API" }
-  , swaggerPaths = mempty
-      { swaggerPathsMap =
-          [ ("/todo/{id}", mempty
-              { swaggerPathItemGet = Just mempty
-                  { swaggerOperationResponses = mempty
-                      { swaggerResponsesResponses =
-                          [ (200, mempty
-                              { swaggerResponseSchema = Just mempty
-                                { swaggerSchemaExample = Just [aesonQQ|
-                                    {
-                                      "created": 100,
-                                      "description": "get milk"
-                                    } |]
-                                , swaggerSchemaType = SwaggerSchemaObject
-                                , swaggerSchemaDescription = Just "This is some real Todo right here"
-                                , swaggerSchemaProperties =
-                                    [ ("created", mempty
-                                        { swaggerSchemaType = SwaggerSchemaInteger
-                                        , swaggerSchemaFormat = Just "int32" })
-                                    , ("description", mempty
-                                        { swaggerSchemaType = SwaggerSchemaString }) ] }
-                              , swaggerResponseDescription = "OK" }) ] }
-                  , swaggerOperationProduces = Just (SwaggerMimeList [ "application/json" ])
-                  , swaggerOperationParameters =
-                      [ mempty
-                          { swaggerParameterRequired = True
-                          , swaggerParameterName = "id"
-                          , swaggerParameterDescription = Just "TodoId param"
-                          , swaggerParameterSchema = SwaggerParameterOther mempty
-                              { swaggerParameterOtherSchemaIn = SwaggerParameterPath
-                              , swaggerParameterOtherSchemaType = SwaggerParamString } } ]
-                  , swaggerOperationTags = [ "todo" ] } }) ] } }
-
-swaggerExampleJSON :: Value
-swaggerExampleJSON = [aesonQQ|
-{
-    "swagger": "2.0",
-    "basePath": "/",
-    "schemes": [
-        "http"
-    ],
-    "info": {
-        "version": "1.0",
-        "title": "Todo API",
-        "license": {
-            "url": "http://mit.com",
-            "name": "MIT"
-        },
-        "description": "This is a an API that tests servant-swagger support for a Todo API"
-    },
-    "paths": {
-        "/todo/{id}": {
-            "get": {
-                "responses": {
-                    "200": {
-                        "schema": {
-                            "example": {
-                                "created": 100,
-                                "description": "get milk"
-                            },
-                            "type": "object",
-                            "description": "This is some real Todo right here",
-                            "properties": {
-                                "created": {
-                                    "format": "int32",
-                                    "type": "integer"
-                                },
-                                "description": {
-                                    "type": "string"
-                                }
-                            }
-                        },
-                        "description": "OK"
-                    }
-                },
-                "produces": [
-                    "application/json"
-                ],
-                "parameters": [
-                    {
-                        "required": true,
-                        "in": "path",
-                        "name": "id",
-                        "type": "string",
-                        "description": "TodoId param"
-                    }
-                ],
-                "tags": [
-                    "todo"
-                ]
-            }
-        }
-    }
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE QuasiQuotes #-}
+module Data.SwaggerSpec where
+
+import Data.Aeson
+import Data.Aeson.QQ
+import qualified Data.Foldable as F
+import Data.HashMap.Strict (HashMap)
+import qualified Data.HashMap.Strict as HashMap
+import Data.Maybe
+import Data.Monoid
+import qualified Data.Vector as Vector
+import Data.Text (Text)
+
+import Data.Swagger
+
+import Test.Hspec
+
+isSubJSON :: Value -> Value -> Bool
+isSubJSON Null _ = True
+isSubJSON (Object x) (Object y) = HashMap.keys x == HashMap.keys i && F.and i
+  where
+    i = HashMap.intersectionWith isSubJSON x y
+isSubJSON (Array xs) (Array ys) = Vector.length xs == Vector.length ys && F.and (Vector.zipWith isSubJSON xs ys)
+isSubJSON x y = x == y
+
+(<~>) :: (Eq a, Show a, ToJSON a, FromJSON a) => a -> Value -> Spec
+x <~> json = do
+  it "encodes correctly (probably with extra properties)" $ do
+    toJSON x `shouldSatisfy` (json `isSubJSON`)
+  it "decodes correctly" $ do
+    fromJSON json `shouldBe` Success x
+
+(<=>) :: (Eq a, Show a, ToJSON a, FromJSON a) => a -> Value -> Spec
+x <=> json = do
+  it "encodes correctly" $ do
+    toJSON x `shouldBe` json
+  it "decodes correctly" $ do
+    fromJSON json `shouldBe` Success x
+
+spec :: Spec
+spec = do
+  describe "License Object" $ licenseExample <=> licenseExampleJSON
+  describe "Contact Object" $ contactExample <=> contactExampleJSON
+  describe "Info Object" $ infoExample <=> infoExampleJSON
+  describe "Operation Object" $ operationExample <~> operationExampleJSON
+  describe "Schema Object" $ do
+    context "Primitive Sample" $ schemaPrimitiveExample <~> schemaPrimitiveExampleJSON
+    context "Simple Model" $ schemaSimpleModelExample <~> schemaSimpleModelExampleJSON
+    context "Model with Map/Dictionary Properties" $ schemaModelDictExample <~> schemaModelDictExampleJSON
+    context "Model with Example" $ schemaWithExampleExample <~> schemaWithExampleExampleJSON
+  describe "Definitions Object" $ definitionsExample <~> definitionsExampleJSON
+  describe "Parameters Definition Object" $ parametersDefinitionExample <~> parametersDefinitionExampleJSON
+  describe "Responses Definition Object" $ responsesDefinitionExample <~> responsesDefinitionExampleJSON
+  describe "Security Definitions Object" $ securityDefinitionsExample <~> securityDefinitionsExampleJSON
+  describe "Swagger Object" $ do
+    context "Todo Example" $ swaggerExample <~> swaggerExampleJSON
+    context "PetStore Example" $
+      it "decodes successfully" $ do
+        fromJSON petstoreExampleJSON `shouldSatisfy` (\x -> case x of Success (_ :: Swagger) -> True; _ -> False)
+
+main :: IO ()
+main = hspec spec
+
+-- =======================================================================
+-- Info object
+-- =======================================================================
+
+infoExample :: SwaggerInfo
+infoExample = SwaggerInfo
+  { _swaggerInfoTitle = "Swagger Sample App"
+  , _swaggerInfoDescription = Just "This is a sample server Petstore server."
+  , _swaggerInfoTermsOfService = Just "http://swagger.io/terms/"
+  , _swaggerInfoContact = Just contactExample
+  , _swaggerInfoLicense = Just licenseExample
+  , _swaggerInfoVersion = "1.0.1" }
+  where
+    license = SwaggerLicense
+      { _swaggerLicenseName = "Apache 2.0"
+      , _swaggerLicenseUrl = Just (URL "http://www.apache.org/licenses/LICENSE-2.0.html") }
+
+infoExampleJSON :: Value
+infoExampleJSON = [aesonQQ|
+{
+  "title": "Swagger Sample App",
+  "description": "This is a sample server Petstore server.",
+  "termsOfService": "http://swagger.io/terms/",
+  "contact": {
+    "name": "API Support",
+    "url": "http://www.swagger.io/support",
+    "email": "support@swagger.io"
+  },
+  "license": {
+    "name": "Apache 2.0",
+    "url": "http://www.apache.org/licenses/LICENSE-2.0.html"
+  },
+  "version": "1.0.1"
+}
+|]
+
+-- =======================================================================
+-- Contact object
+-- =======================================================================
+
+contactExample :: SwaggerContact
+contactExample = SwaggerContact
+  { _swaggerContactName = Just "API Support"
+  , _swaggerContactUrl = Just (URL "http://www.swagger.io/support")
+  , _swaggerContactEmail = Just "support@swagger.io" }
+
+contactExampleJSON :: Value
+contactExampleJSON = [aesonQQ|
+{
+  "name": "API Support",
+  "url": "http://www.swagger.io/support",
+  "email": "support@swagger.io"
+}
+|]
+
+-- =======================================================================
+-- License object
+-- =======================================================================
+
+licenseExample :: SwaggerLicense
+licenseExample = SwaggerLicense
+  { _swaggerLicenseName = "Apache 2.0"
+  , _swaggerLicenseUrl = Just (URL "http://www.apache.org/licenses/LICENSE-2.0.html") }
+
+licenseExampleJSON :: Value
+licenseExampleJSON = [aesonQQ|
+{
+  "name": "Apache 2.0",
+  "url": "http://www.apache.org/licenses/LICENSE-2.0.html"
+}
+|]
+
+
+-- =======================================================================
+-- Operation object
+-- =======================================================================
+
+operationExample :: SwaggerOperation
+operationExample = mempty
+  { _swaggerOperationTags = ["pet"]
+  , _swaggerOperationSummary = Just "Updates a pet in the store with form data"
+  , _swaggerOperationDescription = Just ""
+  , _swaggerOperationOperationId = Just "updatePetWithForm"
+  , _swaggerOperationConsumes = Just (SwaggerMimeList ["application/x-www-form-urlencoded"])
+  , _swaggerOperationProduces = Just (SwaggerMimeList ["application/json", "application/xml"])
+  , _swaggerOperationParameters = params
+  , _swaggerOperationResponses = responses
+  , _swaggerOperationSecurity = security
+  }
+  where
+    security = [SwaggerSecurityRequirement [("petstore_auth", ["write:pets", "read:pets"])]]
+
+    responses = mempty
+      { _swaggerResponsesResponses =
+          [ (200, SwaggerInline mempty { _swaggerResponseDescription = "Pet updated." })
+          , (405, SwaggerInline mempty { _swaggerResponseDescription = "Invalid input" }) ] }
+
+    params = map SwaggerInline
+      [ SwaggerParameter
+          { _swaggerParameterName = "petId"
+          , _swaggerParameterDescription = Just "ID of pet that needs to be updated"
+          , _swaggerParameterRequired = True
+          , _swaggerParameterSchema = SwaggerParameterOther (stringSchema SwaggerParameterPath) }
+      , SwaggerParameter
+          { _swaggerParameterName = "name"
+          , _swaggerParameterDescription = Just "Updated name of the pet"
+          , _swaggerParameterRequired = False
+          , _swaggerParameterSchema = SwaggerParameterOther (stringSchema SwaggerParameterFormData) }
+      , SwaggerParameter
+          { _swaggerParameterName = "status"
+          , _swaggerParameterDescription = Just "Updated status of the pet"
+          , _swaggerParameterRequired = False
+          , _swaggerParameterSchema = SwaggerParameterOther (stringSchema SwaggerParameterFormData) }
+      ]
+
+    stringSchema i = mempty
+      { _swaggerParameterOtherSchemaIn = i
+      , _swaggerParameterOtherSchemaType = SwaggerParamString
+      }
+
+operationExampleJSON :: Value
+operationExampleJSON = [aesonQQ|
+{
+  "tags": [
+    "pet"
+  ],
+  "summary": "Updates a pet in the store with form data",
+  "description": "",
+  "operationId": "updatePetWithForm",
+  "consumes": [
+    "application/x-www-form-urlencoded"
+  ],
+  "produces": [
+    "application/json",
+    "application/xml"
+  ],
+  "parameters": [
+    {
+      "name": "petId",
+      "in": "path",
+      "description": "ID of pet that needs to be updated",
+      "required": true,
+      "type": "string"
+    },
+    {
+      "name": "name",
+      "in": "formData",
+      "description": "Updated name of the pet",
+      "required": false,
+      "type": "string"
+    },
+    {
+      "name": "status",
+      "in": "formData",
+      "description": "Updated status of the pet",
+      "required": false,
+      "type": "string"
+    }
+  ],
+  "responses": {
+    "200": {
+      "description": "Pet updated."
+    },
+    "405": {
+      "description": "Invalid input"
+    }
+  },
+  "security": [
+    {
+      "petstore_auth": [
+        "write:pets",
+        "read:pets"
+      ]
+    }
+  ]
+}
+|]
+
+-- =======================================================================
+-- Schema object
+-- =======================================================================
+
+schemaPrimitiveExample :: SwaggerSchema
+schemaPrimitiveExample = mempty
+  { _swaggerSchemaType = SwaggerSchemaString
+  , _swaggerSchemaFormat = Just "email"
+  }
+
+schemaPrimitiveExampleJSON :: Value
+schemaPrimitiveExampleJSON = [aesonQQ|
+{
+    "type": "string",
+    "format": "email"
+}
+|]
+
+schemaSimpleModelExample :: SwaggerSchema
+schemaSimpleModelExample = mempty
+  { _swaggerSchemaType = SwaggerSchemaObject
+  , _swaggerSchemaRequired = [ "name" ]
+  , _swaggerSchemaProperties =
+      [ ("name", SwaggerInline mempty
+            { _swaggerSchemaType = SwaggerSchemaString } )
+      , ("address", SwaggerRef (SwaggerReference "#/definitions/Address"))
+      , ("age", SwaggerInline mempty
+            { _swaggerSchemaType = SwaggerSchemaInteger
+            , _swaggerSchemaFormat = Just "int32"
+            , _swaggerSchemaCommon = mempty
+                { _swaggerSchemaMinimum = Just 0 } } ) ] }
+
+schemaSimpleModelExampleJSON :: Value
+schemaSimpleModelExampleJSON = [aesonQQ|
+{
+  "type": "object",
+  "required": [
+    "name"
+  ],
+  "properties": {
+    "name": {
+      "type": "string"
+    },
+    "address": {
+      "$ref": "#/definitions/Address"
+    },
+    "age": {
+      "type": "integer",
+      "format": "int32",
+      "minimum": 0
+    }
+  }
+}
+|]
+
+schemaModelDictExample :: SwaggerSchema
+schemaModelDictExample = mempty
+  { _swaggerSchemaType = SwaggerSchemaObject
+  , _swaggerSchemaAdditionalProperties = Just mempty
+      { _swaggerSchemaType = SwaggerSchemaString } }
+
+schemaModelDictExampleJSON :: Value
+schemaModelDictExampleJSON = [aesonQQ|
+{
+  "type": "object",
+  "additionalProperties": {
+    "type": "string"
+  }
+}
+|]
+
+schemaWithExampleExample :: SwaggerSchema
+schemaWithExampleExample = mempty
+  { _swaggerSchemaType = SwaggerSchemaObject
+  , _swaggerSchemaProperties =
+      [ ("id", SwaggerInline mempty
+            { _swaggerSchemaType   = SwaggerSchemaInteger
+            , _swaggerSchemaFormat = Just "int64" })
+      , ("name", SwaggerInline mempty
+            { _swaggerSchemaType = SwaggerSchemaString }) ]
+  , _swaggerSchemaRequired = [ "name" ]
+  , _swaggerSchemaExample = Just [aesonQQ|
+      {
+        "name": "Puma",
+        "id": 1
+      }
+    |] }
+
+schemaWithExampleExampleJSON :: Value
+schemaWithExampleExampleJSON = [aesonQQ|
+{
+  "type": "object",
+  "properties": {
+    "id": {
+      "type": "integer",
+      "format": "int64"
+    },
+    "name": {
+      "type": "string"
+    }
+  },
+  "required": [
+    "name"
+  ],
+  "example": {
+    "name": "Puma",
+    "id": 1
+  }
+}
+|]
+
+-- =======================================================================
+-- Definitions object
+-- =======================================================================
+
+definitionsExample :: HashMap Text SwaggerSchema
+definitionsExample =
+  [ ("Category", mempty
+      { _swaggerSchemaType = SwaggerSchemaObject
+      , _swaggerSchemaProperties =
+          [ ("id", SwaggerInline mempty
+              { _swaggerSchemaType = SwaggerSchemaInteger
+              , _swaggerSchemaFormat = Just "int64" })
+          , ("name", SwaggerInline mempty
+              { _swaggerSchemaType = SwaggerSchemaString }) ] })
+  , ("Tag", mempty
+      { _swaggerSchemaType = SwaggerSchemaObject
+      , _swaggerSchemaProperties =
+          [ ("id", SwaggerInline mempty
+              { _swaggerSchemaType = SwaggerSchemaInteger
+              , _swaggerSchemaFormat = Just "int64" })
+          , ("name", SwaggerInline mempty
+              { _swaggerSchemaType = SwaggerSchemaString }) ] }) ]
+
+definitionsExampleJSON :: Value
+definitionsExampleJSON = [aesonQQ|
+{
+  "Category": {
+    "type": "object",
+    "properties": {
+      "id": {
+        "type": "integer",
+        "format": "int64"
+      },
+      "name": {
+        "type": "string"
+      }
+    }
+  },
+  "Tag": {
+    "type": "object",
+    "properties": {
+      "id": {
+        "type": "integer",
+        "format": "int64"
+      },
+      "name": {
+        "type": "string"
+      }
+    }
+  }
+}
+|]
+
+-- =======================================================================
+-- Parameters Definition object
+-- =======================================================================
+
+parametersDefinitionExample :: HashMap Text SwaggerParameter
+parametersDefinitionExample =
+  [ ("skipParam", mempty
+      { _swaggerParameterName = "skip"
+      , _swaggerParameterDescription = Just "number of items to skip"
+      , _swaggerParameterRequired = True
+      , _swaggerParameterSchema = SwaggerParameterOther mempty
+          { _swaggerParameterOtherSchemaIn = SwaggerParameterQuery
+          , _swaggerParameterOtherSchemaType = SwaggerParamInteger
+          , _swaggerParameterOtherSchemaFormat = Just "int32" } })
+  , ("limitParam", mempty
+      { _swaggerParameterName = "limit"
+      , _swaggerParameterDescription = Just "max records to return"
+      , _swaggerParameterRequired = True
+      , _swaggerParameterSchema = SwaggerParameterOther mempty
+          { _swaggerParameterOtherSchemaIn = SwaggerParameterQuery
+          , _swaggerParameterOtherSchemaType = SwaggerParamInteger
+          , _swaggerParameterOtherSchemaFormat = Just "int32" } }) ]
+
+parametersDefinitionExampleJSON :: Value
+parametersDefinitionExampleJSON = [aesonQQ|
+{
+  "skipParam": {
+    "name": "skip",
+    "in": "query",
+    "description": "number of items to skip",
+    "required": true,
+    "type": "integer",
+    "format": "int32"
+  },
+  "limitParam": {
+    "name": "limit",
+    "in": "query",
+    "description": "max records to return",
+    "required": true,
+    "type": "integer",
+    "format": "int32"
+  }
+}
+|]
+
+-- =======================================================================
+-- Responses Definition object
+-- =======================================================================
+
+responsesDefinitionExample :: HashMap Text SwaggerResponse
+responsesDefinitionExample =
+  [ ("NotFound", mempty { _swaggerResponseDescription = "Entity not found." })
+  , ("IllegalInput", mempty { _swaggerResponseDescription = "Illegal input for operation." }) ]
+
+responsesDefinitionExampleJSON :: Value
+responsesDefinitionExampleJSON = [aesonQQ|
+{
+  "NotFound": {
+    "description": "Entity not found."
+  },
+  "IllegalInput": {
+    "description": "Illegal input for operation."
+  }
+}
+|]
+
+-- =======================================================================
+-- Responses Definition object
+-- =======================================================================
+
+securityDefinitionsExample :: HashMap Text SwaggerSecurityScheme
+securityDefinitionsExample =
+  [ ("api_key", SwaggerSecurityScheme
+      { _swaggerSecuritySchemeType = SwaggerSecuritySchemeApiKey (SwaggerApiKeyParams "api_key" SwaggerApiKeyHeader)
+      , _swaggerSecuritySchemeDescription = Nothing })
+  , ("petstore_auth", SwaggerSecurityScheme
+      { _swaggerSecuritySchemeType = SwaggerSecuritySchemeOAuth2 (SwaggerOAuth2Params
+          { _swaggerOAuth2Flow = SwaggerOAuth2Implicit "http://swagger.io/api/oauth/dialog"
+          , _swaggerOAuth2Scopes =
+              [ ("write:pets",  "modify pets in your account")
+              , ("read:pets", "read your pets") ] } )
+      , _swaggerSecuritySchemeDescription = Nothing }) ]
+
+securityDefinitionsExampleJSON :: Value
+securityDefinitionsExampleJSON = [aesonQQ|
+{
+  "api_key": {
+    "type": "apiKey",
+    "name": "api_key",
+    "in": "header"
+  },
+  "petstore_auth": {
+    "type": "oauth2",
+    "authorizationUrl": "http://swagger.io/api/oauth/dialog",
+    "flow": "implicit",
+    "scopes": {
+      "write:pets": "modify pets in your account",
+      "read:pets": "read your pets"
+    }
+  }
+}
+|]
+
+-- =======================================================================
+-- Swagger object
+-- =======================================================================
+
+swaggerExample :: Swagger
+swaggerExample = mempty
+  { _swaggerBasePath = Just "/"
+  , _swaggerSchemes = Just [Http]
+  , _swaggerInfo = mempty
+      { _swaggerInfoVersion = "1.0"
+      , _swaggerInfoTitle = "Todo API"
+      , _swaggerInfoLicense = Just SwaggerLicense
+          { _swaggerLicenseName = "MIT"
+          , _swaggerLicenseUrl = Just (URL "http://mit.com") }
+      , _swaggerInfoDescription = Just "This is a an API that tests servant-swagger support for a Todo API" }
+  , _swaggerPaths = mempty
+      { _swaggerPathsMap =
+          [ ("/todo/{id}", mempty
+              { _swaggerPathItemGet = Just mempty
+                  { _swaggerOperationResponses = mempty
+                      { _swaggerResponsesResponses =
+                          [ (200, SwaggerInline mempty
+                              { _swaggerResponseSchema = Just $ SwaggerInline mempty
+                                { _swaggerSchemaExample = Just [aesonQQ|
+                                    {
+                                      "created": 100,
+                                      "description": "get milk"
+                                    } |]
+                                , _swaggerSchemaType = SwaggerSchemaObject
+                                , _swaggerSchemaDescription = Just "This is some real Todo right here"
+                                , _swaggerSchemaProperties =
+                                    [ ("created", SwaggerInline mempty
+                                        { _swaggerSchemaType = SwaggerSchemaInteger
+                                        , _swaggerSchemaFormat = Just "int32" })
+                                    , ("description", SwaggerInline mempty
+                                        { _swaggerSchemaType = SwaggerSchemaString }) ] }
+                              , _swaggerResponseDescription = "OK" }) ] }
+                  , _swaggerOperationProduces = Just (SwaggerMimeList [ "application/json" ])
+                  , _swaggerOperationParameters =
+                      [ SwaggerInline mempty
+                          { _swaggerParameterRequired = True
+                          , _swaggerParameterName = "id"
+                          , _swaggerParameterDescription = Just "TodoId param"
+                          , _swaggerParameterSchema = SwaggerParameterOther mempty
+                              { _swaggerParameterOtherSchemaIn = SwaggerParameterPath
+                              , _swaggerParameterOtherSchemaType = SwaggerParamString } } ]
+                  , _swaggerOperationTags = [ "todo" ] } }) ] } }
+
+swaggerExampleJSON :: Value
+swaggerExampleJSON = [aesonQQ|
+{
+    "swagger": "2.0",
+    "basePath": "/",
+    "schemes": [
+        "http"
+    ],
+    "info": {
+        "version": "1.0",
+        "title": "Todo API",
+        "license": {
+            "url": "http://mit.com",
+            "name": "MIT"
+        },
+        "description": "This is a an API that tests servant-swagger support for a Todo API"
+    },
+    "paths": {
+        "/todo/{id}": {
+            "get": {
+                "responses": {
+                    "200": {
+                        "schema": {
+                            "example": {
+                                "created": 100,
+                                "description": "get milk"
+                            },
+                            "type": "object",
+                            "description": "This is some real Todo right here",
+                            "properties": {
+                                "created": {
+                                    "format": "int32",
+                                    "type": "integer"
+                                },
+                                "description": {
+                                    "type": "string"
+                                }
+                            }
+                        },
+                        "description": "OK"
+                    }
+                },
+                "produces": [
+                    "application/json"
+                ],
+                "parameters": [
+                    {
+                        "required": true,
+                        "in": "path",
+                        "name": "id",
+                        "type": "string",
+                        "description": "TodoId param"
+                    }
+                ],
+                "tags": [
+                    "todo"
+                ]
+            }
+        }
+    }
+}
+|]
+
+petstoreExampleJSON :: Value
+petstoreExampleJSON = [aesonQQ|
+{  
+   "swagger":"2.0",
+   "info":{  
+      "description":"This is a sample server Petstore server.  You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/).  For this sample, you can use the api key `special-key` to test the authorization filters.",
+      "version":"1.0.0",
+      "title":"Swagger Petstore",
+      "termsOfService":"http://swagger.io/terms/",
+      "contact":{  
+         "email":"apiteam@swagger.io"
+      },
+      "license":{  
+         "name":"Apache 2.0",
+         "url":"http://www.apache.org/licenses/LICENSE-2.0.html"
+      }
+   },
+   "host":"petstore.swagger.io",
+   "basePath":"/v2",
+   "tags":[  
+      {  
+         "name":"pet",
+         "description":"Everything about your Pets",
+         "externalDocs":{  
+            "description":"Find out more",
+            "url":"http://swagger.io"
+         }
+      },
+      {  
+         "name":"store",
+         "description":"Access to Petstore orders"
+      },
+      {  
+         "name":"user",
+         "description":"Operations about user",
+         "externalDocs":{  
+            "description":"Find out more about our store",
+            "url":"http://swagger.io"
+         }
+      }
+   ],
+   "schemes":[  
+      "http"
+   ],
+   "paths":{  
+      "/pet":{  
+         "post":{  
+            "tags":[  
+               "pet"
+            ],
+            "summary":"Add a new pet to the store",
+            "description":"",
+            "operationId":"addPet",
+            "consumes":[  
+               "application/json",
+               "application/xml"
+            ],
+            "produces":[  
+               "application/xml",
+               "application/json"
+            ],
+            "parameters":[  
+               {  
+                  "in":"body",
+                  "name":"body",
+                  "description":"Pet object that needs to be added to the store",
+                  "required":true,
+                  "schema":{  
+                     "$ref":"#/definitions/Pet"
+                  }
+               }
+            ],
+            "responses":{  
+               "405":{  
+                  "description":"Invalid input"
+               }
+            },
+            "security":[  
+               {  
+                  "petstore_auth":[  
+                     "write:pets",
+                     "read:pets"
+                  ]
+               }
+            ]
+         },
+         "put":{  
+            "tags":[  
+               "pet"
+            ],
+            "summary":"Update an existing pet",
+            "description":"",
+            "operationId":"updatePet",
+            "consumes":[  
+               "application/json",
+               "application/xml"
+            ],
+            "produces":[  
+               "application/xml",
+               "application/json"
+            ],
+            "parameters":[  
+               {  
+                  "in":"body",
+                  "name":"body",
+                  "description":"Pet object that needs to be added to the store",
+                  "required":true,
+                  "schema":{  
+                     "$ref":"#/definitions/Pet"
+                  }
+               }
+            ],
+            "responses":{  
+               "400":{  
+                  "description":"Invalid ID supplied"
+               },
+               "404":{  
+                  "description":"Pet not found"
+               },
+               "405":{  
+                  "description":"Validation exception"
+               }
+            },
+            "security":[  
+               {  
+                  "petstore_auth":[  
+                     "write:pets",
+                     "read:pets"
+                  ]
+               }
+            ]
+         }
+      },
+      "/pet/findByStatus":{  
+         "get":{  
+            "tags":[  
+               "pet"
+            ],
+            "summary":"Finds Pets by status",
+            "description":"Multiple status values can be provided with comma seperated strings",
+            "operationId":"findPetsByStatus",
+            "produces":[  
+               "application/xml",
+               "application/json"
+            ],
+            "parameters":[  
+               {  
+                  "name":"status",
+                  "in":"query",
+                  "description":"Status values that need to be considered for filter",
+                  "required":true,
+                  "type":"array",
+                  "items":{  
+                     "type":"string",
+                     "enum":[  
+                        "available",
+                        "pending",
+                        "sold"
+                     ],
+                     "default":"available"
+                  },
+                  "collectionFormat":"csv"
+               }
+            ],
+            "responses":{  
+               "200":{  
+                  "description":"successful operation",
+                  "schema":{  
+                     "type":"array",
+                     "items":{  
+                        "$ref":"#/definitions/Pet"
+                     }
+                  }
+               },
+               "400":{  
+                  "description":"Invalid status value"
+               }
+            },
+            "security":[  
+               {  
+                  "petstore_auth":[  
+                     "write:pets",
+                     "read:pets"
+                  ]
+               }
+            ]
+         }
+      },
+      "/pet/findByTags":{  
+         "get":{  
+            "tags":[  
+               "pet"
+            ],
+            "summary":"Finds Pets by tags",
+            "description":"Muliple tags can be provided with comma seperated strings. Use tag1, tag2, tag3 for testing.",
+            "operationId":"findPetsByTags",
+            "produces":[  
+               "application/xml",
+               "application/json"
+            ],
+            "parameters":[  
+               {  
+                  "name":"tags",
+                  "in":"query",
+                  "description":"Tags to filter by",
+                  "required":true,
+                  "type":"array",
+                  "items":{  
+                     "type":"string"
+                  },
+                  "collectionFormat":"csv"
+               }
+            ],
+            "responses":{  
+               "200":{  
+                  "description":"successful operation",
+                  "schema":{  
+                     "type":"array",
+                     "items":{  
+                        "$ref":"#/definitions/Pet"
+                     }
+                  }
+               },
+               "400":{  
+                  "description":"Invalid tag value"
+               }
+            },
+            "security":[  
+               {  
+                  "petstore_auth":[  
+                     "write:pets",
+                     "read:pets"
+                  ]
+               }
+            ]
+         }
+      },
+      "/pet/{petId}":{  
+         "get":{  
+            "tags":[  
+               "pet"
+            ],
+            "summary":"Find pet by ID",
+            "description":"Returns a single pet",
+            "operationId":"getPetById",
+            "produces":[  
+               "application/xml",
+               "application/json"
+            ],
+            "parameters":[  
+               {  
+                  "name":"petId",
+                  "in":"path",
+                  "description":"ID of pet to return",
+                  "required":true,
+                  "type":"integer",
+                  "format":"int64"
+               }
+            ],
+            "responses":{  
+               "200":{  
+                  "description":"successful operation",
+                  "schema":{  
+                     "$ref":"#/definitions/Pet"
+                  }
+               },
+               "400":{  
+                  "description":"Invalid ID supplied"
+               },
+               "404":{  
+                  "description":"Pet not found"
+               }
+            },
+            "security":[  
+               {  
+                  "api_key":[  
+                  ]
+               }
+            ]
+         },
+         "post":{  
+            "tags":[  
+               "pet"
+            ],
+            "summary":"Updates a pet in the store with form data",
+            "description":"",
+            "operationId":"updatePetWithForm",
+            "consumes":[  
+               "application/x-www-form-urlencoded"
+            ],
+            "produces":[  
+               "application/xml",
+               "application/json"
+            ],
+            "parameters":[  
+               {  
+                  "name":"petId",
+                  "in":"path",
+                  "description":"ID of pet that needs to be updated",
+                  "required":true,
+                  "type":"integer",
+                  "format":"int64"
+               },
+               {  
+                  "name":"name",
+                  "in":"formData",
+                  "description":"Updated name of the pet",
+                  "required":false,
+                  "type":"string"
+               },
+               {  
+                  "name":"status",
+                  "in":"formData",
+                  "description":"Updated status of the pet",
+                  "required":false,
+                  "type":"string"
+               }
+            ],
+            "responses":{  
+               "405":{  
+                  "description":"Invalid input"
+               }
+            },
+            "security":[  
+               {  
+                  "petstore_auth":[  
+                     "write:pets",
+                     "read:pets"
+                  ]
+               }
+            ]
+         },
+         "delete":{  
+            "tags":[  
+               "pet"
+            ],
+            "summary":"Deletes a pet",
+            "description":"",
+            "operationId":"deletePet",
+            "produces":[  
+               "application/xml",
+               "application/json"
+            ],
+            "parameters":[  
+               {  
+                  "name":"api_key",
+                  "in":"header",
+                  "required":false,
+                  "type":"string"
+               },
+               {  
+                  "name":"petId",
+                  "in":"path",
+                  "description":"Pet id to delete",
+                  "required":true,
+                  "type":"integer",
+                  "format":"int64"
+               }
+            ],
+            "responses":{  
+               "400":{  
+                  "description":"Invalid pet value"
+               }
+            },
+            "security":[  
+               {  
+                  "petstore_auth":[  
+                     "write:pets",
+                     "read:pets"
+                  ]
+               }
+            ]
+         }
+      },
+      "/pet/{petId}/uploadImage":{  
+         "post":{  
+            "tags":[  
+               "pet"
+            ],
+            "summary":"uploads an image",
+            "description":"",
+            "operationId":"uploadFile",
+            "consumes":[  
+               "multipart/form-data"
+            ],
+            "produces":[  
+               "application/json"
+            ],
+            "parameters":[  
+               {  
+                  "name":"petId",
+                  "in":"path",
+                  "description":"ID of pet to update",
+                  "required":true,
+                  "type":"integer",
+                  "format":"int64"
+               },
+               {  
+                  "name":"additionalMetadata",
+                  "in":"formData",
+                  "description":"Additional data to pass to server",
+                  "required":false,
+                  "type":"string"
+               },
+               {  
+                  "name":"file",
+                  "in":"formData",
+                  "description":"file to upload",
+                  "required":false,
+                  "type":"file"
+               }
+            ],
+            "responses":{  
+               "200":{  
+                  "description":"successful operation",
+                  "schema":{  
+                     "$ref":"#/definitions/ApiResponse"
+                  }
+               }
+            },
+            "security":[  
+               {  
+                  "petstore_auth":[  
+                     "write:pets",
+                     "read:pets"
+                  ]
+               }
+            ]
+         }
+      },
+      "/store/inventory":{  
+         "get":{  
+            "tags":[  
+               "store"
+            ],
+            "summary":"Returns pet inventories by status",
+            "description":"Returns a map of status codes to quantities",
+            "operationId":"getInventory",
+            "produces":[  
+               "application/json"
+            ],
+            "parameters":[  
+            ],
+            "responses":{  
+               "200":{  
+                  "description":"successful operation",
+                  "schema":{  
+                     "type":"object",
+                     "additionalProperties":{  
+                        "type":"integer",
+                        "format":"int32"
+                     }
+                  }
+               }
+            },
+            "security":[  
+               {  
+                  "api_key":[  
+                  ]
+               }
+            ]
+         }
+      },
+      "/store/order":{  
+         "post":{  
+            "tags":[  
+               "store"
+            ],
+            "summary":"Place an order for a pet",
+            "description":"",
+            "operationId":"placeOrder",
+            "produces":[  
+               "application/xml",
+               "application/json"
+            ],
+            "parameters":[  
+               {  
+                  "in":"body",
+                  "name":"body",
+                  "description":"order placed for purchasing the pet",
+                  "required":true,
+                  "schema":{  
+                     "$ref":"#/definitions/Order"
+                  }
+               }
+            ],
+            "responses":{  
+               "200":{  
+                  "description":"successful operation",
+                  "schema":{  
+                     "$ref":"#/definitions/Order"
+                  }
+               },
+               "400":{  
+                  "description":"Invalid Order"
+               }
+            }
+         }
+      },
+      "/store/order/{orderId}":{  
+         "get":{  
+            "tags":[  
+               "store"
+            ],
+            "summary":"Find purchase order by ID",
+            "description":"For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions",
+            "operationId":"getOrderById",
+            "produces":[  
+               "application/xml",
+               "application/json"
+            ],
+            "parameters":[  
+               {  
+                  "name":"orderId",
+                  "in":"path",
+                  "description":"ID of pet that needs to be fetched",
+                  "required":true,
+                  "type":"integer",
+                  "maximum":5.0,
+                  "minimum":1.0,
+                  "format":"int64"
+               }
+            ],
+            "responses":{  
+               "200":{  
+                  "description":"successful operation",
+                  "schema":{  
+                     "$ref":"#/definitions/Order"
+                  }
+               },
+               "400":{  
+                  "description":"Invalid ID supplied"
+               },
+               "404":{  
+                  "description":"Order not found"
+               }
+            }
+         },
+         "delete":{  
+            "tags":[  
+               "store"
+            ],
+            "summary":"Delete purchase order by ID",
+            "description":"For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors",
+            "operationId":"deleteOrder",
+            "produces":[  
+               "application/xml",
+               "application/json"
+            ],
+            "parameters":[  
+               {  
+                  "name":"orderId",
+                  "in":"path",
+                  "description":"ID of the order that needs to be deleted",
+                  "required":true,
+                  "type":"string",
+                  "minimum":1.0
+               }
+            ],
+            "responses":{  
+               "400":{  
+                  "description":"Invalid ID supplied"
+               },
+               "404":{  
+                  "description":"Order not found"
+               }
+            }
+         }
+      },
+      "/user":{  
+         "post":{  
+            "tags":[  
+               "user"
+            ],
+            "summary":"Create user",
+            "description":"This can only be done by the logged in user.",
+            "operationId":"createUser",
+            "produces":[  
+               "application/xml",
+               "application/json"
+            ],
+            "parameters":[  
+               {  
+                  "in":"body",
+                  "name":"body",
+                  "description":"Created user object",
+                  "required":true,
+                  "schema":{  
+                     "$ref":"#/definitions/User"
+                  }
+               }
+            ],
+            "responses":{  
+               "default":{  
+                  "description":"successful operation"
+               }
+            }
+         }
+      },
+      "/user/createWithArray":{  
+         "post":{  
+            "tags":[  
+               "user"
+            ],
+            "summary":"Creates list of users with given input array",
+            "description":"",
+            "operationId":"createUsersWithArrayInput",
+            "produces":[  
+               "application/xml",
+               "application/json"
+            ],
+            "parameters":[  
+               {  
+                  "in":"body",
+                  "name":"body",
+                  "description":"List of user object",
+                  "required":true,
+                  "schema":{  
+                     "type":"array",
+                     "items":{  
+                        "$ref":"#/definitions/User"
+                     }
+                  }
+               }
+            ],
+            "responses":{  
+               "default":{  
+                  "description":"successful operation"
+               }
+            }
+         }
+      },
+      "/user/createWithList":{  
+         "post":{  
+            "tags":[  
+               "user"
+            ],
+            "summary":"Creates list of users with given input array",
+            "description":"",
+            "operationId":"createUsersWithListInput",
+            "produces":[  
+               "application/xml",
+               "application/json"
+            ],
+            "parameters":[  
+               {  
+                  "in":"body",
+                  "name":"body",
+                  "description":"List of user object",
+                  "required":true,
+                  "schema":{  
+                     "type":"array",
+                     "items":{  
+                        "$ref":"#/definitions/User"
+                     }
+                  }
+               }
+            ],
+            "responses":{  
+               "default":{  
+                  "description":"successful operation"
+               }
+            }
+         }
+      },
+      "/user/login":{  
+         "get":{  
+            "tags":[  
+               "user"
+            ],
+            "summary":"Logs user into the system",
+            "description":"",
+            "operationId":"loginUser",
+            "produces":[  
+               "application/xml",
+               "application/json"
+            ],
+            "parameters":[  
+               {  
+                  "name":"username",
+                  "in":"query",
+                  "description":"The user name for login",
+                  "required":true,
+                  "type":"string"
+               },
+               {  
+                  "name":"password",
+                  "in":"query",
+                  "description":"The password for login in clear text",
+                  "required":true,
+                  "type":"string"
+               }
+            ],
+            "responses":{  
+               "200":{  
+                  "description":"successful operation",
+                  "schema":{  
+                     "type":"string"
+                  },
+                  "headers":{  
+                     "X-Rate-Limit":{  
+                        "type":"integer",
+                        "format":"int32",
+                        "description":"calls per hour allowed by the user"
+                     },
+                     "X-Expires-After":{  
+                        "type":"string",
+                        "format":"date-time",
+                        "description":"date in UTC when toekn expires"
+                     }
+                  }
+               },
+               "400":{  
+                  "description":"Invalid username/password supplied"
+               }
+            }
+         }
+      },
+      "/user/logout":{  
+         "get":{  
+            "tags":[  
+               "user"
+            ],
+            "summary":"Logs out current logged in user session",
+            "description":"",
+            "operationId":"logoutUser",
+            "produces":[  
+               "application/xml",
+               "application/json"
+            ],
+            "parameters":[  
+            ],
+            "responses":{  
+               "default":{  
+                  "description":"successful operation"
+               }
+            }
+         }
+      },
+      "/user/{username}":{  
+         "get":{  
+            "tags":[  
+               "user"
+            ],
+            "summary":"Get user by user name",
+            "description":"",
+            "operationId":"getUserByName",
+            "produces":[  
+               "application/xml",
+               "application/json"
+            ],
+            "parameters":[  
+               {  
+                  "name":"username",
+                  "in":"path",
+                  "description":"The name that needs to be fetched. Use user1 for testing. ",
+                  "required":true,
+                  "type":"string"
+               }
+            ],
+            "responses":{  
+               "200":{  
+                  "description":"successful operation",
+                  "schema":{  
+                     "$ref":"#/definitions/User"
+                  }
+               },
+               "400":{  
+                  "description":"Invalid username supplied"
+               },
+               "404":{  
+                  "description":"User not found"
+               }
+            }
+         },
+         "put":{  
+            "tags":[  
+               "user"
+            ],
+            "summary":"Updated user",
+            "description":"This can only be done by the logged in user.",
+            "operationId":"updateUser",
+            "produces":[  
+               "application/xml",
+               "application/json"
+            ],
+            "parameters":[  
+               {  
+                  "name":"username",
+                  "in":"path",
+                  "description":"name that need to be deleted",
+                  "required":true,
+                  "type":"string"
+               },
+               {  
+                  "in":"body",
+                  "name":"body",
+                  "description":"Updated user object",
+                  "required":true,
+                  "schema":{  
+                     "$ref":"#/definitions/User"
+                  }
+               }
+            ],
+            "responses":{  
+               "400":{  
+                  "description":"Invalid user supplied"
+               },
+               "404":{  
+                  "description":"User not found"
+               }
+            }
+         },
+         "delete":{  
+            "tags":[  
+               "user"
+            ],
+            "summary":"Delete user",
+            "description":"This can only be done by the logged in user.",
+            "operationId":"deleteUser",
+            "produces":[  
+               "application/xml",
+               "application/json"
+            ],
+            "parameters":[  
+               {  
+                  "name":"username",
+                  "in":"path",
+                  "description":"The name that needs to be deleted",
+                  "required":true,
+                  "type":"string"
+               }
+            ],
+            "responses":{  
+               "400":{  
+                  "description":"Invalid username supplied"
+               },
+               "404":{  
+                  "description":"User not found"
+               }
+            }
+         }
+      }
+   },
+   "securityDefinitions":{  
+      "petstore_auth":{  
+         "type":"oauth2",
+         "authorizationUrl":"http://petstore.swagger.io/api/oauth/dialog",
+         "flow":"implicit",
+         "scopes":{  
+            "write:pets":"modify pets in your account",
+            "read:pets":"read your pets"
+         }
+      },
+      "api_key":{  
+         "type":"apiKey",
+         "name":"api_key",
+         "in":"header"
+      }
+   },
+   "definitions":{  
+      "Order":{  
+         "type":"object",
+         "properties":{  
+            "id":{  
+               "type":"integer",
+               "format":"int64"
+            },
+            "petId":{  
+               "type":"integer",
+               "format":"int64"
+            },
+            "quantity":{  
+               "type":"integer",
+               "format":"int32"
+            },
+            "shipDate":{  
+               "type":"string",
+               "format":"date-time"
+            },
+            "status":{  
+               "type":"string",
+               "description":"Order Status",
+               "enum":[  
+                  "placed",
+                  "approved",
+                  "delivered"
+               ]
+            },
+            "complete":{  
+               "type":"boolean",
+               "default":false
+            }
+         },
+         "xml":{  
+            "name":"Order"
+         }
+      },
+      "Category":{  
+         "type":"object",
+         "properties":{  
+            "id":{  
+               "type":"integer",
+               "format":"int64"
+            },
+            "name":{  
+               "type":"string"
+            }
+         },
+         "xml":{  
+            "name":"Category"
+         }
+      },
+      "User":{  
+         "type":"object",
+         "properties":{  
+            "id":{  
+               "type":"integer",
+               "format":"int64"
+            },
+            "username":{  
+               "type":"string"
+            },
+            "firstName":{  
+               "type":"string"
+            },
+            "lastName":{  
+               "type":"string"
+            },
+            "email":{  
+               "type":"string"
+            },
+            "password":{  
+               "type":"string"
+            },
+            "phone":{  
+               "type":"string"
+            },
+            "userStatus":{  
+               "type":"integer",
+               "format":"int32",
+               "description":"User Status"
+            }
+         },
+         "xml":{  
+            "name":"User"
+         }
+      },
+      "Tag":{  
+         "type":"object",
+         "properties":{  
+            "id":{  
+               "type":"integer",
+               "format":"int64"
+            },
+            "name":{  
+               "type":"string"
+            }
+         },
+         "xml":{  
+            "name":"Tag"
+         }
+      },
+      "Pet":{  
+         "type":"object",
+         "required":[  
+            "name",
+            "photoUrls"
+         ],
+         "properties":{  
+            "id":{  
+               "type":"integer",
+               "format":"int64"
+            },
+            "category":{  
+               "$ref":"#/definitions/Category"
+            },
+            "name":{  
+               "type":"string",
+               "example":"doggie"
+            },
+            "photoUrls":{  
+               "type":"array",
+               "xml":{  
+                  "name":"photoUrl",
+                  "wrapped":true
+               },
+               "items":{  
+                  "type":"string"
+               }
+            },
+            "tags":{  
+               "type":"array",
+               "xml":{  
+                  "name":"tag",
+                  "wrapped":true
+               },
+               "items":{  
+                  "$ref":"#/definitions/Tag"
+               }
+            },
+            "status":{  
+               "type":"string",
+               "description":"pet status in the store",
+               "enum":[  
+                  "available",
+                  "pending",
+                  "sold"
+               ]
+            }
+         },
+         "xml":{  
+            "name":"Pet"
+         }
+      },
+      "ApiResponse":{  
+         "type":"object",
+         "properties":{  
+            "code":{  
+               "type":"integer",
+               "format":"int32"
+            },
+            "type":{  
+               "type":"string"
+            },
+            "message":{  
+               "type":"string"
+            }
+         }
+      }
+   },
+   "externalDocs":{  
+      "description":"Find out more about Swagger",
+      "url":"http://swagger.io"
+   }
 }
 |]
