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

Support URI input with "hrefSchema" #228

Merged
merged 2 commits into from
Jan 23, 2017

Conversation

handrews
Copy link
Contributor

@handrews handrews commented Jan 10, 2017

[EDIT: This PR now does not remove "method", nor does it drop "href" preprocessing]

This introduces "hrefSchema" which provides a schema for user input
matching the "href" URI Template variables.

The meta-schemas have been updated accordingly.


Here are some examples (note that "method": "get" is the default, but is included for clarity):

Here is a Draft 05 "get" with parameters:

{
    "href": "/examples",
    "method": "get",
    "encType": "application/x-www-form-urlencoded",
    "schema": {
        "properties": {
            "name": {"type": "string"},
            "whatever": {"type": "number"}
        }
    }
}

Here is the equivalent using "hrefSchema" (note "name" and "whatever" in the URI Template). It is not necessary to specify "x-www-form-urlencoded" here, as the "{?name,whatever}" form of URI template variable specifically generates that format.

{
    "href": "/examples{?name,whatever}",
    "hrefSchema": {
        "properties": {
            "name": {"type": "string"},
            "whatever": {"type": "number"}
        }
    },
    "method": "get"
}

That's not an incredibly compelling improvement, so here is an "hrefSchema" example that cannot be expressed with "schema" and "encType":

{
    "href": "/examples/{id}",
    "hrefSchema": {
        "properties": {
            "id": {
                "type": "integer",
                "minimum": 1
            }
        }
    },
    "method": "get"
}

This allows the user to provide their own "id" value if they already know which id they need.

@handrews
Copy link
Contributor Author

This PR has been updated to only add "hrefSchema". It no longer removes "method" or the "href" preprocessing.

This is the absolute minimal form of this change. I'm pretty sure. (of course, me saying that I couldn't split this to @awwright on IRC today caused me to realize that I could absolutely split it and it made a lot of sense to do so, so... yeah.)

@Relequestual you may want to look it over again, although the only differences from what you approved are very minor changes to make it work with "href" preprocessing and clarify how it works with "method" and "schema".

</t>
<t>
Omitting "hrefSchema" or setting the entire schema to "false" prevents
any user input from being accepted.
Copy link
Member

Choose a reason for hiding this comment

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

This feels different to how we normally do things. If I read that right, you're saying that omitting hrefSchema will always result in a validation fail if user input is provided. This now means that the URI template is useless without defining the validation with hrefSchema, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@Relequestual no, it just means that you can't provide user input to resolve the template. In other words, if "hrefSchema" is absent, everything works exactly the same as it does now. That seemed preferable, although I take your point that we usually allow things unless forbidden.

I was also kind of going by how I think "schema" works. I think that if "schema" is not present, then there is no input allowed via that route. But going back and reading it, it's not really clear whether that is intended to be 'you can only provide input if "schema" is present' or 'if there is no schema, you can provide any input'.

Given how "schema" and "encType" are generally described, I think it/they need to be present for input to be allowed. If that is indeed the case, then "hrefSchema" should have the same behavior. If that is not the case, and a missing "schema" means any and all input is allowed, then yes, "hrefSchema" should be changed to behave that way as well.

Either way, we should also clarify the behavior when "schema" is absent.

Copy link
Contributor Author

@handrews handrews Jan 17, 2017

Choose a reason for hiding this comment

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

@Relequestual I figured out why it made sense to me to do it this way.

Validation is a constraint system. An empty schema validates everything, and every keyword you add restricts the set in some way.

Hyper-schema defines functionality. So in my head thats an additive capability approach. A blank hyper-schema indicates that there are no known hypermedia transitions, not that all possible transitions should work. So to me, it's philosophically consistent to look at a link and say that a minimal link defines minimal functionality. In order to know that it takes user input, it has to declare that it does.

I can see an argument in the other direction, though. I just wanted to explain why it felt consistent to me. I view it as a different conceptual model than validation.

Choose a reason for hiding this comment

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

@handrews @Relequestual

Hyper-schema defines functionality. So in my head thats an additive capability approach. A blank hyper-schema indicates that there are no known hypermedia transitions, not that all possible transitions should work. So to me, it's philosophically consistent to look at a link and say that a minimal link defines minimal functionality.

One reason to take the additive approach that @handrews outlines is that it forces the user to define a schema whenever there are URI template variables to resolve, I think that is a nice feature because otherwise it suggests that you can provide any data whatsoever, where the object 's properties must coincidentally align with the URI template variables in run-time, sort of how it's set up currently. Perhaps the schema keyword has been previously used for this purpose in addition to validation, I can't really say. If this is true, I believe preventing schema from being used for multiple purposes is a good thing, that way one turning knob doesn't have two potential effects.

In order to know that it takes user input, it has to declare that it does.

I agree, the template alone isn't enough to say "I accept some data" because you're then left with the question of "well what kind of data do you accept?". In an ecosystem essentially based around defining comparable types, I'd argue it's pretty essential. Perhaps we could also say: "hrefSchema is only required and used for validation if there are URI template variables to resolve, otherwise it is / should be ignored"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

the template alone isn't enough to say "I accept some data" because you're then left with the question of "well what kind of data do you accept?".

Yes, the naïve answer which I tried when implementing a previous project is to just look up the part of the instance schema that corresponds to the instance data that you would use to resolve that template variable. If you have a simple object for your instance, that's easy enough to do. But if you have some complex beast of "oneOf"s and "not" and "dependencies", etc., it's challenging. And not even possible unless you have an instance available.

It was very messy to implement, hence me deciding to require that input schemas be specified on their own rather than inferred. Explicit is better than implicit.

This adds a more flexible and powerful mechansim for allowing
user input into the template resolution process.  It offers
a superset of the functionality available by using the "schema"
field with "method"="get".
to keep the user input validation constraints identical to the
instance validation constraints for the corresponding property,
while "id" is given a false schema to prevent user input for
that variable.
Copy link
Member

Choose a reason for hiding this comment

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

I understand the first part of this explanation, but not the second part.

..."id" is given a false schema to prevent user input for that variable

For easy reference...

...
"href": "/things/{id}{?extra}",
        "hrefSchema": {
            "properties": {
                "id": false,
                "extra": {"$ref": "#/definitions/extra"}
            }
        }
...

Maybe this is my lack of understand of HyperSchema, but how does having it in hrefSchema allow it as input? In terms of input in the URL? If so, is it implying that an invalid URI is things/123 while a valid URI is things/abc? This is really unclear and confusing to me.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK, @Relequestual and I talked on IRC and identified some unclear wording that led to his confusion. I am going to rework that and then update this PR.

@handrews
Copy link
Contributor Author

@Relequestual I expanded the one line about "supporting form-style functionality" into a section on links and data which goes over a couple of different ways of using links and how those uses relate to external vs instance data.

I moved the language more towards "external data", keeping some references to "user input" but making them specific types of external data. Hopefully this starts separating data input from user input in the minds of hyper-schema authors, since hyper-schema is not limited to interactive work.

@Relequestual
Copy link
Member

Relequestual commented Jan 19, 2017

After our discussion on irc, I believe I understand this addition now, but some re-phrasing may be required to clarify what's happening in the example I commented on.
Github didn't show me your comment before I typed mine... reviewing.

Copy link
Member

@Relequestual Relequestual left a comment

Choose a reason for hiding this comment

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

I think maybe my real problem with this addition isn't this addition, but that I don't feel href is defined well enough. How do I know that "href": "/thing/{id} means the id of the instance. I would guess I'm probably missing the explanation for that, but if not, we need to add it.

To avoid doubt, the changes you've made here are good =] Thanks for the update PR.

@handrews
Copy link
Contributor Author

To clarify for everyone, @Relequestual and I discussed his concerns about how one knows that {id} means the id of the instance on another IRC session about an hour ago. The things that were confusing him were things that were present already that I did not make worse (mostly, the preprocessing stuff makes everything horrible confusing, so as we've long discussed, as soon as this PR gets approved I will submit a second PR that removes that mess).

So now we are just waiting for @awwright 's review.
@Relequestual has given formal approval and re-affirmed it in his last comment.
@slurmulon has made supportive comments (not sure it will allow him to officially approve).

@awwright , the ball is in your court.

@awwright awwright merged commit 8d1ce31 into json-schema-org:master Jan 23, 2017
@handrews handrews deleted the hrefschema branch January 23, 2017 22:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants