Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle schemas with no type. #148

Merged
merged 2 commits into from
Feb 15, 2022
Merged

Conversation

bombaywalla
Copy link
Contributor

This partially addresses #145.

If a schema has no "type" key, and ONLY has a "properties" key, then
it is a valid schema and 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.

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.
@oliyh
Copy link
Owner

oliyh commented Feb 14, 2022

Hello,

Thanks for your continued work on this. From reading the spec, it seems like it could be expressed as:

(s/either {(s/optional k) v ...} ;; if it's an object and it includes _any_ of these properties
          s/Any ;; does not mean the value has to be an object
          )

It's not pretty, but seems to closer match the intention of the spec. What do you think?

@bombaywalla
Copy link
Contributor Author

What you have is more accurate with respect to the spec. I'd guess that in the particular example I am dealing with, the person writing the spec just meant for it to be an object, and didn't understand the subtleties.

Would you like me to modify the PR to make it what you suggest?

@oliyh
Copy link
Owner

oliyh commented Feb 15, 2022

I'm inclined to agree with you, it seems a bit rubbish that it would allow "foo" through, and actually I don't think schema would give the right behaviour anyway. Consider:

Properties of foo and bar as ints in the schema, and the user supplies {:foo 123 :bar "not a number"}. This would pass the schema I wrote above, because it would fail the map schema but then pass the Any schema. From the wording, because the keys are present, they should use the map schema only and therefore fail.

Really, the 'correct' implementation is this:

(s/conditional 
  #(some? % [:foo :bar]) 
  {(s/optional-key :foo) s/Int 
   (s/optional-key :bar) s/Int} 

  :else s/Any)

But this seems to be getting overly complicated now. I think, given that no one has raised an issue about this before, that we go with your implementation and we can always adjust it later if it causes problems for someone else.

;; 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 (and (= (count ks) 1) (= (first ks) :properties)) "object")))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole let block could probably be simplified to (= #{:properties} (set (keys schema)))

@bombaywalla
Copy link
Contributor Author

Made the code improvement you suggested.

@oliyh oliyh merged commit 6793c7a into oliyh:master Feb 15, 2022
@oliyh
Copy link
Owner

oliyh commented Feb 15, 2022

Many thanks once again

@bombaywalla
Copy link
Contributor Author

You're welcome Thanks for martian and for guiding the PRs to successful merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants