Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 7ab2455

Browse files
committed
Add most of a collection example.
There are some things that are not addressed here, and most importantly this highlights the problems that I wrote about in issue #421. Hopefully they are more clear when laid out like this and noted in CREFs. I feel like it is a prerequisite of a hypermedia format that claims to be feature-complete to be able to recognize self-describing collections and make use of them without having specific knowledge of the data type of their contents.
1 parent b17612c commit 7ab2455

File tree

1 file changed

+298
-2
lines changed

1 file changed

+298
-2
lines changed

‎jsonschema-hyperschema.xml‎

Lines changed: 298 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@
440440
<section title='"self" links' anchor="self">
441441
<t>
442442
A hyper-schema implementation MUST recognize that a link with relation
443-
type "self" that is applicable to the entire instance document describes
443+
type "self" that is applicable to the entire instance document describes
444444
how a user agent can interact with the resource represented by that
445445
instance document. A "self" link MUST be resolvable from the instance,
446446
and therefore "hrefSchema" MUST NOT be present.
@@ -1465,7 +1465,7 @@ Link: <https://schema.example.com/entry> rel=describedBy
14651465
<![CDATA[{
14661466
"$id": "https://schema.example.com/thing",
14671467
"$schema": "http://json-schema.org/draft-07-wip/hyper-schema#",
1468-
"base": "http://api.example.com",
1468+
"base": "https://api.example.com",
14691469
"type": "object",
14701470
"required": ["data"],
14711471
"properties": {
@@ -1722,6 +1722,302 @@ Link: <https://schema.example.com/entry> rel=describedBy
17221722
Discovering ordered links
17231723
Multiple self links (for the collection and each item)
17241724
</cref></t>
1725+
<t>
1726+
In many systems, individual resources are grouped into collections. Those
1727+
collections also often provide a way to create individual item resources with
1728+
server-assigned identifiers.
1729+
</t>
1730+
<t>
1731+
This schema describes a collection where each item representation is
1732+
identical to the individual resource item representation, and there
1733+
is enough metadata included in the collection representation to
1734+
produce pagination links. The "first" and "last" pagination links
1735+
were omitted as this is already a long example.
1736+
</t>
1737+
<t>
1738+
Note that there is an object member called "items", which is an array
1739+
and thefore uses the validation keyword "items" in its own schema. The outer
1740+
"items" is a property name, the inner one is a schema keyword.
1741+
</t>
1742+
<figure>
1743+
<artwork>
1744+
<![CDATA[{
1745+
"$id": "https://schema.example.com/thing-collection",
1746+
"$schema": "http://json-schema.org/draft-07-wip/hyper-schema#",
1747+
"base": "https://api.example.com",
1748+
"type": "object",
1749+
"required": ["items"],
1750+
"properties": {
1751+
"items": {
1752+
"type": "array",
1753+
"items": {
1754+
"allOf": [{"$ref": "thing#"}],
1755+
"links": [
1756+
{
1757+
"anchorPointer": "",
1758+
"rel": "item",
1759+
"href": "things/{id}",
1760+
"hrefRequired": ["id"],
1761+
"targetSchema": {"$ref": "thing#"}
1762+
}
1763+
]
1764+
}
1765+
},
1766+
"meta": {
1767+
"type": "object",
1768+
"properties": {
1769+
"prev": {"$ref": "#/definitions/scrolling"},
1770+
"current": {"$ref": "#/definitions/scrolling"},
1771+
"next": {"$ref": "#/definitions/scrolling"}
1772+
}
1773+
}
1774+
},
1775+
"links": [
1776+
{
1777+
"rel": "self",
1778+
"href": "things{?offset,limit}",
1779+
"hrefRequired": ["offset", "limit"],
1780+
"hrefPointers": {
1781+
"offset": "/meta/current/offset",
1782+
"limit": "/meta/current/limit"
1783+
},
1784+
"targetSchema": {"$ref": "#"}
1785+
},
1786+
{
1787+
"rel": "prev",
1788+
"href": "things{?offset,limit}",
1789+
"hrefRequired": ["offset", "limit"],
1790+
"hrefPointers": {
1791+
"offset": "/meta/prev/offset",
1792+
"limit": "/meta/prev/limit"
1793+
},
1794+
"targetSchema": {"$ref": "#"}
1795+
},
1796+
{
1797+
"rel": "next",
1798+
"href": "things{?offset,limit}",
1799+
"hrefRequired": ["offset", "limit"],
1800+
"hrefPointers": {
1801+
"offset": "/meta/next/offset",
1802+
"limit": "/meta/next/limit"
1803+
},
1804+
"targetSchema": {"$ref": "#"}
1805+
}
1806+
],
1807+
"definitions": {
1808+
"scrolling": {
1809+
"type": "object",
1810+
"properties": {
1811+
"offset": {
1812+
"type": "integer",
1813+
"minimum": 0,
1814+
"default": 0
1815+
},
1816+
"limit": {
1817+
"type": "integer",
1818+
"minimum": 1,
1819+
"maximum": 100,
1820+
"default": 10
1821+
}
1822+
}
1823+
}
1824+
}
1825+
}]]>
1826+
</artwork>
1827+
<postamble>
1828+
Notice that the "self" link includes the pagination query
1829+
that produced the exact representation, rather than being
1830+
a generic link to the collection allowing selecting the
1831+
page via input. There is no link for manual page selection
1832+
in the example as shown here, nor is there a "submissionSchema"
1833+
for item creation, but we will consider those additions further down.
1834+
</postamble>
1835+
</figure>
1836+
<figure>
1837+
<artwork>
1838+
<![CDATA[{
1839+
"items": [
1840+
{"id": 12345, "data": {}},
1841+
{"id": 67890, "data": {}}
1842+
],
1843+
"meta": {
1844+
"current": {
1845+
"offset": 0,
1846+
"limit": 2
1847+
},
1848+
"next": {
1849+
"offset": 3,
1850+
"limit": 2
1851+
}
1852+
}
1853+
}]]>
1854+
</artwork>
1855+
</figure>
1856+
<figure>
1857+
<preamble>
1858+
Here are all of the links that apply to this instance,
1859+
including those that are referenced by using the "thing"
1860+
schema for the individual items. The "self" links for
1861+
the overal resource and each individual item are
1862+
distinguished by different context pointers. Note also
1863+
that the "item" and "self" links for a given thing have
1864+
identical target URIs but different context pointers.
1865+
</preamble>
1866+
<artwork>
1867+
<![CDATA[[
1868+
{
1869+
"contextUri": "https://api.example.com/things",
1870+
"contextPointer": "",
1871+
"rel": "self",
1872+
"targetUri": "https://api.example.com/things?offset=20,limit=2",
1873+
"attachmentPointer": ""
1874+
},
1875+
{
1876+
"contextUri": "https://api.example.com/things",
1877+
"contextPointer": "",
1878+
"rel": "next",
1879+
"targetUri": "https://api.example.com/things?offset=22,limit=2",
1880+
"attachmentPointer": ""
1881+
},
1882+
{
1883+
"contextUri": "https://api.example.com/things",
1884+
"contextPointer": "",
1885+
"rel": "item",
1886+
"targetUri": "https://api.example.com/things/1234",
1887+
"attachmentPointer": "/items/0"
1888+
},
1889+
{
1890+
"contextUri": "https://api.example.com/things",
1891+
"contextPointer": "",
1892+
"rel": "item",
1893+
"targetUri": "https://api.example.com/things/67890",
1894+
"attachmentPointer": "/items/1"
1895+
},
1896+
{
1897+
"contextUri": "https://api.example.com/things",
1898+
"contextPointer": "/items/0",
1899+
"rel": "self",
1900+
"targetUri": "https://api.example.com/things/1234",
1901+
"attachmentPointer": "/items/0"
1902+
},
1903+
{
1904+
"contextUri": "https://api.example.com/things",
1905+
"contextPointer": "/items/1",
1906+
"rel": "self",
1907+
"targetUri": "https://api.example.com/things/67890",
1908+
"attachmentPointer": "/items/1"
1909+
}
1910+
]]]>
1911+
1912+
</artwork>
1913+
<postamble>
1914+
Note that there is no "prev" link in the output, as we are looking
1915+
at the first page. The lack of a "prev" field under "meta",
1916+
together with the "prev" link's "hrefRequired" values, means
1917+
that the link is not usable with this particular instance.
1918+
</postamble>
1919+
</figure>
1920+
<t>
1921+
To fully specify our collection, we also need to add the following
1922+
link to our "thing" schema. Note that this would cause it to also
1923+
appear as a link in each item in the collection representation, which
1924+
is a good example of why it is best to only construct links upon request.
1925+
There is no need for having as many functionally identical "collection"
1926+
links as there are items in a collection page on every collection
1927+
representation.
1928+
</t>
1929+
<figure>
1930+
<preamble>
1931+
This link would be added to the top-level "links" array in the
1932+
"https://schemasexample.com/thing" schema.
1933+
</preamble>
1934+
<artwork>
1935+
<![CDATA[{
1936+
"rel": "collection",
1937+
"href": "/things",
1938+
"targetSchema": {"$ref": "thing-collection#"},
1939+
"submissionSchema": {"$ref": "#"}
1940+
}]]>
1941+
</artwork>
1942+
<postamble>
1943+
Here we see the "submissionSchema" indicating that we can create
1944+
a single "thing" by submitting a representation (minus server-created
1945+
fields such as "id") to the collection that is this link's target
1946+
schema. While we cannot, in general, make assumptions about the
1947+
semantics of making a data submission request (in HTTP terms, a POST),
1948+
<xref target="collectionAndItem" /> tells us that we MAY make such
1949+
an assumption when the link relation is "collection", and that
1950+
hyper-schema authors MUST NOT use a "collection" link if the data
1951+
submission operation has semantics other than item creation.
1952+
</postamble>
1953+
</figure>
1954+
<t>
1955+
<cref>
1956+
I left off the scrolling parameters for this link. Technically,
1957+
the link should go to the page containing the specific "thing"
1958+
that is the context of the link. If the collection is using
1959+
semantic sorting, then this is do-able (ideally setting
1960+
the page boundary such that this is the first item, and allowing
1961+
input on the page count / "limit" parameter). But getting into
1962+
semantic scrolling/pagination seems way too involved for this
1963+
example.
1964+
</cref>
1965+
</t>
1966+
<t>
1967+
<cref>
1968+
Note also that POST-ing to a collection page that will not contain
1969+
the created item also seems weird. While retrieving the collection
1970+
from a query parameter-less URI will still retrieve a page, that's
1971+
a limit imposed by the server. POST-ing to such a URI and disregarding
1972+
the "default" values for the parameters seems correct. This is another
1973+
reason to *not* automatically write default values into the query.
1974+
</cref>
1975+
</t>
1976+
<t>
1977+
But what if we do not have any "thing"s yet? We cannot get to the
1978+
individual "thing" schema as there is no individual "thing" to fetch.
1979+
And the "tag:rel.example.com,2017:thing" link in the entry point
1980+
resource does not indicate how to create a "thing". The "self" link
1981+
requires the "id" to already exist, but it is assigned by the server.
1982+
So we need to add another link to our entry point schema:
1983+
</t>
1984+
<figure>
1985+
<preamble>
1986+
This LDO would be added to the top-level "links" array in the entry
1987+
point resource's hyper-schema.
1988+
</preamble>
1989+
<artwork>
1990+
<![CDATA[{
1991+
"rel": "tag:rel.example.com,2017:thing-collection",
1992+
"href": "/things{?offset,limit}",
1993+
"hrefSchema": {
1994+
"$ref": "thing-collection#/definitions/scrolling"
1995+
},
1996+
"submissionSchema": {
1997+
"$ref": "thing#"
1998+
},
1999+
"targetSchema": {
2000+
"$ref": "thing-collection#"
2001+
}
2002+
}]]>
2003+
</artwork>
2004+
<postamble>
2005+
Now we see the scrolling parameters being accepted as input, so
2006+
we can jump to any scroll window within the collection.
2007+
</postamble>
2008+
</figure>
2009+
<t>
2010+
<cref>
2011+
Here we also see the "submissionSchema" to use to create a "thing",
2012+
but how do we recognize it? We can't use a "collection" link relation
2013+
here, because there is no identifiable "thing" to serve as the context
2014+
resource. We could look at the submission schema, notice that it
2015+
has a "collection" link and is therefore an item, and notice that
2016+
its "collection" link produces the same(-ish?) URI, but that seems
2017+
overly complicated and also gets into trouble with query parameters
2018+
again.
2019+
</cref>
2020+
</t>
17252021
</section>
17262022
</section>
17272023

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /