   (cond (s/optional-key? schema-key)
         [(.k schema-key) false]
 
+        ;; This is the normal alternative to s/optional-key
+        (keyword? schema-key)
+        [schema-key true]
+
+        ;; This can happen in vector schemas, but is still legit in map schemas:
         (s/required-key? schema-key)
         [(.k schema-key) true]
 
-        (keyword? schema-key)
-        [schema-key true]
-
         :else
         (throw (RuntimeException. (format "No idea what to do with query schema key %s." schema-key)))))
+
+(defn- simple->swagger-schema
+  "Converts a simple (non-object) Schema into an inline Swagger Schema, with keys :type and perhaps :format, etc."
+  [swagger-options schema]
+  (cond-let
+    [data-type-mappings (:data-type-mappings swagger-options)
+     data (get data-type-mappings schema)]
+
+    (some? data)
+    data
+
+    (instance? EnumSchema schema)
+    {:type :string                                          ; an assumption
+     :enum (unwrap-schema schema)}
+
+    (instance? Maybe schema)
+    (assoc (simple->swagger-schema swagger-options (unwrap-schema schema))
+      :allowEmptyValue true)
+
+    ;; The i.a.r.schema/with-description macro often turns bare classes into an IsInstance
+    (instance? IsInstance schema)
+    (recur swagger-options (unwrap-schema schema))
+
+    ;; TODO: arrays
+
+    :else
+    (throw (ex-info (format "Unable to convert schema %s to Swagger." schema)
+                    {:schema schema}))))
 
 (defn default-query-params-injector
   "Identifies each query parameter via the :query-schema metadata and injects it."
   [swagger-options swagger-object routing-entry params-key]
   (if-let [schema (-> routing-entry :meta :query-schema)]
     ;; Assumes that the schema is a map.
-    (try
-      (let [reducer (fn [so [key-id key-schema]]
-                      (cond-let
-                        ;; Just ignore these, they are a convinience for the caller ("be generous in what you accept").
-                        (= s/Any key-id)
-                        so
-
-                        [[k required] (reduce-schema-key key-id)]
-
-                        :else
-                        (update-in so params-key
-                                   conj {:name     k
-                                         :in       :query
-                                         :required required})))]
-        (reduce reducer swagger-object schema))
-      (catch Exception e
-        (throw (ex-info "Unable to convert routing entry into Swagger data."
-                        routing-entry
-                        e))))
+    (let [reducer (fn [so [key-id key-schema]]
+                    (cond-let
+                      ;; Just ignore these, they are a convinience for the caller ("be generous in what you accept").
+                      (= s/Any key-id)
+                      so
+
+                      [[k required] (reduce-schema-key key-id)]
+
+                      :else
+                      (t/track
+                        (format "Describing query parameter `%s'." (name k))
+                        (let [schema-description (simple->swagger-schema swagger-options key-schema)
+                              full-description (assoc schema-description
+                                                 :name k
+                                                 :in :query
+                                                 :required required)]
+                          (update-in so params-key
+                                     conj full-description)))))]
+      (reduce reducer swagger-object schema))
     ; no :query-schema
     swagger-object))
 
-(defn schema->swagger-schema
+(defn map->swagger-schema
   [swagger-options schema]
-  ;; To be done!
-  (medley/remove-vals nil?
-                      {:required    []
-                       ;; :description is often provided by with-description, which overrides the normal docstring.
-                       :description (or (-> schema meta :description)
-                                        (-> schema meta :doc))
-                       :properties  {}}))
+  (let [reducer (fn [o [schema-key schema-value]]
+                  (let [[k required?] (reduce-schema-key schema-key)]
+                    (t/track
+                      #(format "Describing body key `%s'." (name k))
+                      (let [swagger-schema (simple->swagger-schema swagger-options schema-value)]
+                        (cond-> (assoc-in o [:properties k] swagger-schema)
+                                required? (update-in [:required] conj k))))))]
+    (->>
+      schema
+      remove-any-keys
+      (reduce reducer {:description (or (-> schema meta :description)
+                                        (-> schema meta :doc))})
+      remove-nil-vals)))
 
 (defn to-schema-reference
   "Converts a schema to a schema reference; the schema must be named.  Returns a tuple

(defn default-body-params-injector
  "Uses the :body-schema metadata to identify the body params."
  [swagger-options swagger-object routing-entry paths-key]
  (if-let [schema (-> routing-entry :meta :body-schema)]

    ;; Assumption: it's a map and named
    (let [[swagger-object' schema-reference] (to-schema-reference swagger-options swagger-object schema)]
      (update-in swagger-object' paths-key
                 conj {:name     :request-body
                       :in       :body
                       :required true
                       :schema   schema-reference}))
    ; no schema:
    swagger-object))

(defn default-responses-injector
  "Uses the :responses metadata to identify possible responses."
  [swagger-options swagger-object routing-entry paths-key]
  (let [responses (-> routing-entry :meta :responses)
        reducer (fn [so [status-code schema]]
                  (let [schema-meta (meta schema)
                        description (or (:description schema-meta)
                                        (:doc schema-meta)
                                        "Documentation not provided.")]
                    (assoc-in so (concat paths-key [:responses (str status-code)]) {:description description})))]
    (reduce reducer swagger-object responses)))

(defn default-path-item-object-injector

  Adapter for ring-swagger. Converts an intermediate description of the namespaces
  into a description compatible with the ring-swagger library."
  (:require [schema.core :as s]
            [io.aviso.rook.schema :refer [unwrap-schema]]
            [clojure.string :as str]
            [medley.core :as medley]
            [io.aviso.toolchest.macros :refer [cond-let]]
            [io.aviso.toolchest.collections :refer [pretty-print]]
            [io.aviso.tracker :as t]
            [clojure.tools.logging :as l]
            [io.aviso.rook.utils :as utils])
  (:import [schema.core EnumSchema Maybe]
           [io.aviso.rook.schema IsInstance]))

(defn- remove-nil-vals
  [m]
  (medley/remove-vals nil? m))

(defn- remove-any-keys
  "Removes keys that are equaly to s/Any."
  [m]
  (medley/remove-vals #(= s/Any %) m))

(def default-swagger-skeleton
  "A base skeleton for a Swagger Object (as per the Swagger 2.0 specification), that is further populated from Rook namespace
