Skip to content

Commit

Permalink
Handle schemas with no type. (#148)
Browse files Browse the repository at this point in the history
* Handle schemas with no type.

If a schema has no "type" key, and ONLY has a "properties" key, then
we can reasonably assume that the type is "object".

See OAI/OpenAPI-Specification#1657

Excerpt:
A particularly common form of this is a schema that omits type, but specifies properties.
Strictly speaking, this does not mean that the value must be an object.
It means that if the value is an object, and it includes any of those properties,
the property values must conform to the corresponding property subschemas.

In reality, this construct almost always means that the user intends type: object,
and I think it would be reasonable for a code generator to assume this,
maybe with a validation: strict|lax config option to control that behavior.

* Improve code as per @oliyh's suggestion.
  • Loading branch information
bombaywalla authored Feb 15, 2022
1 parent 1689a49 commit 6793c7a
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 1 deletion.
18 changes: 17 additions & 1 deletion core/src/martian/openapi.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,23 @@
components
(conj seen-set reference)))
(wrap schema
(condp = (:type schema)
(condp = (if-let [typ (:type schema)]
typ
;; If a schema has no :type key, and the only key it contains is a :properties key,
;; then the :type can reasonably be inferred as "object".
;;
;; See https://github.com/OAI/OpenAPI-Specification/issues/1657
;;
;; Excerpt:
;; A particularly common form of this is a schema that omits type, but specifies properties.
;; Strictly speaking, this does not mean that the value must be an object.
;; It means that if the value is an object, and it includes any of those properties,
;; the property values must conform to the corresponding property subschemas.
;;
;; In reality, this construct almost always means that the user intends type: object,
;; and I think it would be reasonable for a code generator to assume this,
;; maybe with a validation: strict|lax config option to control that behavior.
(when (= #{:properties} (set (keys schema))) "object"))
"array" [(openapi->schema (:items schema) components seen-set)]
"object" (let [required? (set (:required schema))]
(into {}
Expand Down
27 changes: 27 additions & 0 deletions core/test/martian/openapi_test.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -160,3 +160,30 @@
{:status (s/eq 404)
:body {(s/optional-key :code) s/Int (s/optional-key :details) s/Str}}]
(:response-schemas handler)))))

(deftest schemas-without-type-test
(let [openapi-json
{:paths {(keyword "/models")
{:get {:operationId "list-models"
:summary "Lists models"
:responses {:404 {:$ref "#/components/responses/NotFound"}}}}}
:components {:responses {:NotFound
{:description "The requested resource was not found."
:content
{:application/json
{:schema {:$ref "#/components/schemas/Error"}}}}}
:schemas {:Error
{:properties
{:code
{:description "An enumerated error for machine use.",
:type "integer",
:readOnly true},
:details
{:description "A human-readable description of the error.",
:type "string",
:readOnly true}}}}}}
[handler] (openapi->handlers openapi-json {:encodes ["application/json"]
:decodes ["application/json"]})]
(is (= [{:status (s/eq 404)
:body {(s/optional-key :code) s/Int (s/optional-key :details) s/Str}}]
(:response-schemas handler)))))

0 comments on commit 6793c7a

Please sign in to comment.