json-schema-org / json-hyperschema-spec

A *future* location for the JSON Hyper-Schema I-D sources.
14 stars 4 forks source link

templating for "rel" and other LDO keywords #1

Open handrews opened 7 years ago

handrews commented 7 years ago

Originally written by @geraintluff at https://github.com/json-schema/json-schema/wiki/More-templating-(v5-proposal)

Proposed keywords

Uses existing keywords - proposes extension of rel in LDOs.

Other keywords in LDOs could also be subject to this (e.g. mediaType) - however, rel is the most obvious candidate as it is also a URI.

(Yes, in case that was unclear - link relation values are basically all secretly URIs.)

Purpose

Currently, the only property of links that is templated is "href". However, some data formats actually include other link information in the data as well - most often rel (although sometimes others such as media type).

Values

The allowed values would be exactly the same as for href (including the extended templating syntax from issue json-schema-org/json-schema-spec#52 , if applicable).

Behaviour

To obtain the value for the link relation, the value of rel is interpreted in exactly the same way as href.

Concerns

As such, it is probably safe to allow rel to have the same behaviour as href, and this is unlikely to cause incompatability with existing v4 schemas.

If $data makes it into the standard, then we probably don't need to enable templating for anything apart from href and rel - everything else can be referenced wholesale from the data.

awwright commented 7 years ago

Curly braces aren't even legal in URIs or URI references, hence their use in URI Templates. Also angle brackets <> which are used to quote URIs.

handrews commented 7 years ago

@awwright true, I just copied and pasted this one without reading it too closely. Should I edit the initial comment to take out the stuff about { and } in URIs?

handrews commented 7 years ago

@awwright I removed the discussion about {braces} as you suggested. I also took the gigantic quote out of your comment because it added doubled the length of the conversation without (I think) adding much. I hope that is OK, my apologies if not (it's easy enough to restore if you'd prefer).

handrews commented 6 years ago

I'm having trouble figuring out the use case here. If rel is the only thing with a template variable, then this is just a complex way to define multiple links, each with a different (or potentially different) relationship. I don't see this done in a common enough way to make it worth having a special syntax.

On the other hand, if both rel and href are templated, I can come up with a contrived use case. Assume the following is the schema for a "pets" field in a person resource of some sort:

{
    "type": "object",
    "additionalProperties": {
        "type": "object",
        "properties": {
            "id": {"type": "integer", "minimum": 1}
            "animalType": {"type": "string"}
        },
        "links": [
            {
                "anchorPointer": "",
                "rel": "tag:example.com,2017:pet-{animalType}",
                "href": "pets/{id}"
            }
        ]
    }
}

So if you have something like:

{
    "Fido": {
        "id": 1,
        "animalType": "dog"
    },
    "Derp": {
        "id": 2,
        "animalType": "cat"
    }
}

then you now have two links from the person resource, one of type "pet-dog" and one of type "pet-cat".

Technically, you can only do this with rel templating, as using oneOf would require you to enumerate all possible pet types. But I'm still not sold on this as a really necessary thing. I don't think that being able to rewrite an example in a different way invalidates a use case, but I can't come up with a really compelling use case here. This one feels like bad design in some way, at least to me.

Does anyone have a use case for this? Does anyone feel strongly enough about this that it's worth keeping open? If not, I'm inclined to close it. If we find a new use case, we can open it again.

handrews commented 6 years ago

I actually came up with a use case for this. As a use case, it's contrived, but it's contrived from a real-world JSON format, JSON-HAL:

This hyper-schema would make non-templated, non-curied JSON HAL links usable by hyper-schema clients. Said clients would have to figure out whether they've ended up with a curie or a usable URI, which is the contrived / incomplete part.

The "0#" Relative JSON Pointer resolves to the name of the current property. It is not a URI reference and the # is not a fragment marker. In HAL, the property names of the _links object are the link relation types.

The "0/href" pointer is technically unnecessary as it's the default value but I figure it makes things a bit more clear.

{
    "properties": {
        "_links": {
            "additionalProperties": {
                "links": [
                    {   
                        "rel": "{propertyName}",
                        "href": "{href}",
                        "templatePointers": {
                            "propertyName": "0#",
                            "href": "0/href"
                        },  
                        "templateRequired": ["href"]
                    }   
                ]   
            }   
        },  
        "_embedded": {
            "additionalProperties": {
                "oneOf": [
                    {"$ref": "#"},
                    {"items": {"$ref": "#"}}
                ]
            }
        } 
    }   
}