Please check the errata for any errors or issues reported since publication.
This document is also available in this non-normative format: ePub
The English version of this specification is the only normative version. Non-normative translations may also be available.
Copyright © 2015 W3C® (MIT, ERCIM, Keio, Beihang). W3C liability, trademark and document use rules apply.
This document defines the procedures and rules to be applied when converting tabular data into JSON. Tabular data may be complemented with metadata annotations that describe its structure, the meaning of its content and how it may form part of a collection of interrelated tabular data. This document specifies the effect of this metadata on the resulting JSON.
This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.
The CSV on the Web Working Group was chartered to produce a recommendation "Access methods for CSV Metadata" as well as recommendations for "Metadata vocabulary for CSV data" and "Mapping mechanism to transforming CSV into various formats (e.g., RDF, JSON, or XML)". This document aims to satisfy the JSON variant of the mapping recommendation.
This document was published by the CSV on the Web Working Group as a Recommendation. If you wish to make comments regarding this document, please send them to [email protected] (subscribe, archives). All comments are welcome.
Please see the Working Group's implementation report.
This document has been reviewed by W3C Members, by software developers, and by other W3C groups and interested parties, and is endorsed by the Director as a W3C Recommendation. It is a stable document and may be used as reference material or cited from another document. W3C's role in making the Recommendation is to draw attention to the specification and to promote its widespread deployment. This enhances the functionality and interoperability of the Web.
This document was produced by a group operating under the 5 February 2004 W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.
This document is governed by the 1 September 2015 W3C Process Document.
This document describes the processing of tabular data to create a set of nested objects that MUST be serialized as JSON [RFC7159].
The conversion of CSV content to JSON is intended for web developers who need not care about the complexities of RDF [rdf11-concepts]. Where the formality of RDF is required, [csv2rdf] provides the procedures for mapping from CSV content to RDF which may be serialized to [json-ld].
The [tabular-data-model] defines an annotated tabular data model consisting of tables, columns, rows, and cells, enriched with annotations that describe the structure of the tabular data and the meaning of its content. A group of tables is a collection of tables published as a single atomic unit.
The conversion procedure described in this specification operates on the annotated tabular data model. This specification does not specify the processes needed to convert CSV-encoded data into tabular data form. Please refer to [tabular-data-model] for details of parsing tabular data.
Conversion applications MUST provide at least two modes of operation: standard and minimal.
Standard mode conversion frames the information gleaned from the cells of the tabular data with details of the rows, tables, and a group of tables within which that information is provided.
Minimal mode conversion includes only the information gleaned from the cells of the tabular data within the output.
Standard and minimal conversion are described normatively below.
Conversion applications MAY offer additional implementation specific conversion modes.
Transformation definitions, as defined in [tabular-metadata] MAY be used to specify how tabular data can be transformed into another format using a script or template. Such transformation definitions MAY use the JSON output described in this specification as input.
As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.
The key words MAY, MUST, and SHOULD are to be interpreted as described in [RFC2119].
Tabular data MUST conform to the description from [tabular-data-model]. In particular note that each row MUST contain the same number of cells (although some of these cells may be empty).
Not all CSV-encoded data can be parsed into a tabular data model. An algorithm for parsing CSV-based files is described in [tabular-data-model].
The following typographic conventions are used in this specification:
markup
markup definition reference
markup external definition reference
Notes are in light green boxes with a green left border and with a "Note" header in green. Notes are normative or informative depending on the whether they are in a normative or informative section, respectively.
Examples are in light khaki boxes, with khaki left border, and with a numbered "Example" header in khaki. Examples are always informative. The content of the example is in monospace font and may be syntax colored.
The procedures for converting tabular data into JSON are described below for both standard and minimal modes.
null
or a sequence of values.notes
property. This may be an empty list.null
.A conformant JSON conversion application MUST produce output conforming to this algorithm according to the chosen mode of conversion: standard or minimal.
Where an annotated table is defined in isolation (e.g. in the absence of a group of tables), a default group of tables is provided with a single tables annotation that refers to the given table.
The [tabular-data-model] specifies that string values within tabular data (such as column titles or cell string values) MUST contain only Unicode characters. No Unicode normalization (as specified in [UAX15]) is applied to these string values during the conversion to JSON.
The steps in the algorithm defined here apply to minimal mode.
Insert an empty array A into the JSON output. The objects containing the name-value pairs associated with the cell values will be subsequently inserted into this array.
Each table is processed sequentially in the order they are referenced in the group of tables. For each table where the suppress output annotation is false
:
Each row within the table is processed sequentially in order. For each row in the current table:
Generate a sequence of objects, S1 to Sn, each of which corresponds to a subject described by the current row, as described in 4.3 Generating Objects.
As described in 4.4 Generating Nested Objects, process the sequence of objects, S1 to Sn, to produce a new sequence of root objects, SR1 to SRm, that MAY include nested objects.
The steps in the algorithm defined here apply to standard mode.
Insert an empty object G into the JSON output which is associated with the group of tables.
If the group of tables has an identifier IG; insert the following name-value pair into object G:
@id
Insert any notes and non-core annotations specified for the group of tables into object G according to the rules provided in 5. JSON-LD to JSON.
Insert the following name-value pair into object G:
tables
where AT is an array into which the objects describing the annotated tables will be subsequently inserted.
Each table is processed sequentially in the order they are referenced in the group of tables.
For each table where the suppress output annotation is false
:
Insert an empty object T into the array AT to represent the table.
If the table has an identifier IT; insert the following name-value pair into object T:
@id
Specify the source tabular data file URL for the current table based on the url annotation; insert the following name-value pair into object T:
url
Insert any notes and non-core annotations specified for the table into object T according to the rules provided in 5. JSON-LD to JSON.
All other core annotations for the table are ignored during the conversion; including information about table schemas and their columns, foreign keys, table direction, transformations, etc.
Insert the following name-value pair into object T:
row
where AR is an array into which the objects describing the rows will be subsequently inserted.
Each row within the table is processed sequentially in order. For each row in the current table:
Insert an empty object R into the array AR to represent the row.
Specify the row number n for the row; insert the following name-value pair into object R:
rownum
Specify the row source number nsource for the row within the source tabular data file URL using a fragment-identifier as specified in [RFC7111]; if row source number is not null
, insert the following name-value pair into object R:
url
#row=
nsourceSpecify any titles for the row; if row titles is not null
, insert the following name-value pair into object R:
titles
where t is the single value or array of values provided by the row titles annotation.
JSON has no native support for expressing language information; therefore any such information associated with the row titles is ignored.
Insert any non-core annotations specified for the row into object R according to the rules provided in 5. JSON-LD to JSON.
Insert the following name-value pair into object R:
describes
where A is an array. The objects containing the name-value pairs associated with the cell values will be subsequently inserted into this array.
Generate a sequence of objects, S1 to Sn, each of which corresponds to a subject described by the current row, as described in 4.3 Generating Objects.
As described in 4.4 Generating Nested Objects, process the sequence of objects, S1 to Sn, to produce a new sequence of root objects, SR1 to SRm, that MAY include nested objects.
The steps in the algorithm defined here apply to both standard and minimal modes.
This algorithm generates a sequence of objects, S1 to Sn, each of which corresponds to a subject described by the current row. The algorithm inserts name-value pairs into Si depending on the cell values as outlined in the following steps.
Determine the unique subjects for the current row. The subject(s) described by each row are determined according to the about URL annotation for each cell in the current row. A default subject for the row is used for any cells where about URL is undefined.
For each subject that the current row describes where at least one of the cells that refers to that subject has a value or value URL that is not null
, and is associated with a column where suppress output annotation is false
:
Create an empty object Si to represent the subject i.
(i is the index number with values from 1 to n, where n is the number of subjects for the row)
Subject i is identified according to the about URL annotation of its associated cells: IS. For a default subject where about URL is not specified by its cells, IS is null
.
If the identifier for subject i, IS, is not null
, then insert the following name-value pair into object Si:
@id
Each cell referring to subject i is then processed sequentially according to the order of the columns.
For each cell referring to subject i, where the suppress output annotation for the column associated with that cell is false
, insert a name-value pair into object Si as described below:
If the value of property URL for the cell is not null
, then name N takes the value of property URL compacted according to the rules as defined in URL Compaction in [tabular-metadata].
Else, name N takes the URI decoded value of the name annotation for the column associated with the cell. (URI decoding is necessary as name may have been encoded if it was taken from a supplied title.)
If the value URL for the current cell is not null
, then insert the following name-value pair into object Si:
where Vurl is the value of value URL annotation for the current cell expressed as a string in the JSON output. If N is @type
, compact Vurl according to the rules as defined in URL Compaction in [tabular-metadata].
Else, if the cell value is a list that is not empty, then the cell value provides a sequence of values for inclusion within the JSON output; insert an array Av containing each value V of the sequence into object Si:
Each of the values V derived from the sequence MUST be expressed in the JSON output according to the datatype of V as defined below in section 4.5 Interpreting datatypes.
Else, if the cell value is not null
, then the cell value provides a single value V for inclusion within the JSON output; insert the following name-value pair into object Si:
Value V derived from the cell values MUST be expressed in the JSON output according to the datatype of the value as defined in section 4.5 Interpreting datatypes.
If name N occurs more than once within object Si, the name-value pairs from each occurrence of name N MUST be compacted to form a single name-value pair with name N and whose value is an array containing all values from each of those name-value pairs. Where the value from one or more contributing name-value pairs is of type array, the values from contributing arrays are included directly to the resulting array (i.e. arrays of values are flattened).
The steps in the algorithm defined herein apply to both standard and minimal modes.
Where the current row describes multiple subjects, it MAY be possible to organize the objects associated with those subjects such that some objects are nested within others; e.g. where the value URL annotation for one cell matches the about URL annotation for another cell in the same row. This algorithm considers a sequence of objects generated according to 4.3 Generating Objects, S1 to Sn, each of which corresponds to a subject described by the current row. It generates a new sequence of root objects, SR1 to SRm, that MAY include nested objects.
Where the current row describes only a single subject, this algorithm may be bypassed as no nesting is possible. In such a case, the root object SR1 is identical to the original object S1.
This nesting algorithm is based on the interrelationships between subjects described within a given row that are specified using the value URL annotation. Cell values expressing the identity of a subject in the current row (i.e., as a simple literal) will be ignored by this algorithm.
The algorithm uses the following terms:
The nesting algorithm is defined as follows:
For all cells in the current row, determine the value URLs, Vurl, that occur only once. The list of these uniquely occurring value URLs is referred to as the URL-list.
Create an empty forest F. Vertices in the trees of this forest represent the subjects described by the current row.
For each object Si in the sequence S1 to Sn:
Determine the identity of object Si: IS. If present in object Si, the name-value pair with name @id
provides the value of IS. Else, object Si is not explicitly identified and IS is null
.
Check whether there is a vertex N in forest F that represents object Si. If none of the existing vertices in forest F represent object Si, then insert a new tree into forest F whose root is a vertex N that represents object Si and has identity IS.
For all cells associated with the current object Si (e.g. whose about URL annotation matches IS):
If the value URL annotation of the current cell is defined and its value, Vurl, appears in the URL-list, then check each of the other objects in the sequence S1 to Sn to determine if Vurl identifies one of those objects.
For object Sj, if the name-value pair with name @id
is present and its value matches Vurl, then:
If the root of the tree containing vertex N is a vertex that represents object Sj, then object Si is already a descendant of object Sj; no further action SHOULD be taken for this instance of Vurl.
This clause in the algorithm prevents circular loops from being created.
Furthermore, because the URL-list contains value URLs that occur only once for the current row, object Si cannot be a descendant of intermediate vertices in the tree.
Else, if there is a root vertex M in forest F that represents object Sj, then set vertex M as a child of vertex N and remove vertex M from the list of roots in forest F (i.e., the tree rooted by M becomes a sub-tree of N).
Else, create a new vertex M that represents object Sj as a child of vertex N.
Each vertex in forest F represents an object in the original sequence of objects S1 to Sn and is associated with a subject described by the current row. Rearrange objects S1 to Sn such that they mirror the structure of the trees in forest F as follows: If vertex M, representing object Si, is a child of vertex N, representing object Sj, then the name-value pair in object Sj associated with the edge relating M and N MUST be modified such that the (literal) value, Vurl, from that name-value pair is replaced by object Si thus creating a nested object.
An implementation may be able to optimize the algorithm by skipping branches (e.g. if URL-list is empty) or by other means.
Cell values are expressed in the JSON output according to the cell value's datatype. The relationship between the base annotation value of the cell value's datatype and the primitive types supported by JSON (as specified in [RFC7159]) is provided below:
datatype | JSON primitive type |
---|---|
anyAtomicType | string |
anyURI | string |
base64Binary | string |
boolean | boolean |
date | string |
dateTime | string |
dateTimeStamp | string |
decimal | number |
integer | number |
long | number |
int | number |
short | number |
byte | number |
nonNegativeInteger | number |
positiveInteger | number |
unsignedLong | number |
unsignedInt | number |
unsignedShort | number |
unsignedByte | number |
nonPositiveInteger | number |
negativeInteger | number |
double | number |
duration | string |
dayTimeDuration | string |
yearMonthDuration | string |
float | number |
gDay | string |
gMonth | string |
gMonthDay | string |
gYear | string |
gYearMonth | string |
hexBinary | string |
QName | string |
string | string |
normalizedString | string |
token | string |
language | string |
Name | string |
NMTOKEN | string |
xml | string |
html | string |
json | string |
time | string |
Only the base annotation value is used to determine the primitive type used within the JSON output. Additional restrictions to the cell value's datatype, such as the id annotation, are ignored for the purposes of conversion to JSON.
A datatype's format is irrelevant to the conversion procedure defined in this specification; the cell value has already been parsed from the contents of the cell according to the format annotation.
Cell errors MUST be recorded by applications where the contents of a cell cannot be parsed or validated (see Parsing Cells and Validating Tables in [tabular-data-model] respectively). In cases where cell errors are recorded, applications may attempt to determine the appropriate JSON primitive type during the subsequent conversion process according to local rules.
This section defines a mechanism for transforming the [json-ld] dialect used for non-core annotations and notes originating from the processing of metadata (as defined in [tabular-metadata]) into JSON.
Conversion applications may have other means to create annotated tables, e.g. through some application specific APIs. In such cases the exact format for non-core annotations or notes may be different. Specifications for such annotation processes should specify how these annotations are converted into JSON.
Name-value pairs from notes and non-core annotations annotations are generally copied verbatim from the metadata description subject to the exceptions below:
Name-value pairs whose value is an object using the [json-ld] keyword @value
, for example:
{ "@value": "
V" }
are transformed to:
Name-value pairs occurring within the value object that use [json-ld] keywords @language
and @type
are ignored.
Name-value pairs whose value is an object using the [json-ld] keyword @id
to coerce a string-value to be interpreted as an IRI, for example:
{ "@id": "
Vurl" }
are transformed to:
In addition to compacting values of property URLs, URLs which were the value of objects using the [json-ld] keyword @type
are compacted according to the rules as defined in URL Compaction in [tabular-metadata].
This section is non-normative.
Each of the examples expresses more complex conversions - it is recommended that readers of this specification work through the examples in sequential order.
This example comprises a single annotated table containing information attributes about countries; country code, position (latitude, longitude) and name. Whilst the input tabular data file, published at http://example.org/countries.csv
, includes a header line, no further metadata annotations are given. The tabular data file is provided below:
countryCode,latitude,longitude,name AD,42.5,1.6,Andorra AE,23.4,53.8,"United Arab Emirates" AF,33.9,67.7,Afghanistan
The annotated table generated from parsing the tabular data file is shown below and provides the basis for the conversion to JSON.
Annotations for the resulting table T, with 4 columns and 3 rows, are shown below:
id | core annotations | ||
---|---|---|---|
url | columns | rows | |
T | http://example.org/countries.csv | C1, C2, C3, C4 | R1, R2, R3 |
Annotations for the columns, rows and cells in table T are shown in the tables below:
Column annotations:
id | core annotations | |||||
---|---|---|---|---|---|---|
table | number | source number | cells | name | titles | |
C1 | T | 1 | 1 | C1.1, C2.1, C3.1 | countryCode | countryCode |
C2 | T | 2 | 2 | C1.2, C2.2, C3.2 | latitude | latitude |
C3 | T | 3 | 3 | C1.3, C2.3, C3.3 | longitude | longitude |
C4 | T | 4 | 4 | C1.4, C2.4, C3.4 | name | name |
Row annotations:
id | core annotations | |||
---|---|---|---|---|
table | number | source number | cells | |
R1 | T | 1 | 2 | C1.1, C1.2, C1.3, C1.4 |
R2 | T | 2 | 3 | C2.1, C2.2, C2.3, C2.4 |
R3 | T | 3 | 4 | C3.1, C3.2, C3.3, C3.4 |
Cell annotations:
id | core annotations | |||||
---|---|---|---|---|---|---|
table | column | row | string value | value | property URL | |
C1.1 | T | C1 | R1 | "AD" | "AD" | null |
C1.2 | T | C2 | R1 | "42.5" | "42.5" | null |
C1.3 | T | C3 | R1 | "1.6" | "1.6" | null |
C1.4 | T | C4 | R1 | "Andorra" | "Andorra" | null |
C2.1 | T | C1 | R2 | "AE" | "AE" | null |
C2.2 | T | C2 | R2 | "23.4" | "23.4" | null |
C2.3 | T | C3 | R2 | "53.8" | "53.8" | null |
C2.4 | T | C4 | R2 | "United Arab Emirates" | "United Arab Emirates" | null |
C3.1 | T | C1 | R3 | "AF" | "AF" | null |
C3.2 | T | C2 | R3 | "33.9" | "33.9" | null |
C3.3 | T | C3 | R3 | "67.7" | "67.7" | null |
C3.4 | T | C4 | R3 | "Afghanistan" | "Afghanistan" | null |
Minimal mode output for this example is provided below:
[{ "countryCode": "AD", "latitude": "42.5", "longitude": "1.6", "name": "Andorra" }, { "countryCode": "AE", "latitude": "23.4", "longitude": "53.8", "name": "United Arab Emirates" }, { "countryCode": "AF", "latitude": "33.9", "longitude": "67.7", "name": "Afghanistan" }]
The about URL annotation has not been set for cells in table T ({ "url": "http://example.org/countries.csv"}
); cells in a given row where about URL has not been specified are assumed to refer to the same subject and so the name-value pairs associated with the cell values of that row occur within the same object.
Given that the property URL is null
for cells in table T ({ "url": "http://example.org/countries.csv"}
), the simplified name is used in the name-value pairs; e.g. countryCode
rather than http://example.org/countries.csv#countryCode
Standard mode output for this example is provided below:
{ "tables": [{ "url": "http://example.org/countries.csv", "row": [{ "url": "http://example.org/countries.csv#row=2", "rownum": 1, "describes": [{ "countryCode": "AD", "latitude": "42.5", "longitude": "1.6", "name": "Andorra" }] }, { "url": "http://example.org/countries.csv#row=3", "rownum": 2, "describes": [{ "countryCode": "AE", "latitude": "23.4", "longitude": "53.8", "name": "United Arab Emirates" }] }, { "url": "http://example.org/countries.csv#row=4", "rownum": 3, "describes": [{ "countryCode": "AF", "latitude": "33.9", "longitude": "67.7", "name": "Afghanistan" }] }] }] }
Even though the table was defined in isolation, the annotated table is wrapped in a group of tables.
The name-value pair with name url
provides reference to the original tabular data file and to specific rows therein.
The row number is provided for each row using name-value pair with name rownum
.
The object containing the name-values pairs associated with the cell values of a row are related to the object for that row using the name-value pair with name describes
.
This example is based on Use Case #11 - City of Palo Alto Tree Data and comprises a single annotated table describing an inventory of tree maintenance operations. The input tabular data file, published at http://example.org/tree-ops-ext.csv
, and the associated metadata description http://example.org/tree-ops-ext.csv-metadata.json
are provided below:
GID,On Street,Species,Trim Cycle,Diameter at Breast Ht,Inventory Date,Comments,Protected,KML 1,ADDISON AV,Celtis australis,Large Tree Routine Prune,11,10/18/2010,,,"<Point><coordinates>-122.156485,37.440963</coordinates></Point>" 2,EMERSON ST,Liquidambar styraciflua,Large Tree Routine Prune,11,6/2/2010,,,"<Point><coordinates>-122.156749,37.440958</coordinates></Point>" 6,ADDISON AV,Robinia pseudoacacia,Large Tree Routine Prune,29,6/1/2010,cavity or decay; trunk decay; codominant leaders; included bark; large leader or limb decay; previous failure root damage; root decay; beware of BEES,YES,"<Point><coordinates>-122.156299,37.441151</coordinates></Point>"
{ "@context": ["http://www.w3.org/ns/csvw", {"@language": "en"}], "@id": "http://example.org/tree-ops-ext", "url": "tree-ops-ext.csv", "dc:title": "Tree Operations", "dcat:keyword": ["tree", "street", "maintenance"], "dc:publisher": [{ "schema:name": "Example Municipality", "schema:url": {"@id": "http://example.org"} }], "dc:license": {"@id": "http://opendefinition.org/licenses/cc-by/"}, "dc:modified": {"@value": "2010-12-31", "@type": "xsd:date"}, "notes": [{ "@type": "oa:Annotation", "oa:hasTarget": {"@id": "http://example.org/tree-ops-ext"}, "oa:hasBody": { "@type": "oa:EmbeddedContent", "rdf:value": "This is a very interesting comment about the table; it's a table!", "dc:format": {"@value": "text/plain"} } }], "dialect": {"trim": true}, "tableSchema": { "columns": [{ "name": "GID", "titles": [ "GID", "Generic Identifier" ], "dc:description": "An identifier for the operation on a tree.", "datatype": "string", "required": true, "suppressOutput": true }, { "name": "on_street", "titles": "On Street", "dc:description": "The street that the tree is on.", "datatype": "string" }, { "name": "species", "titles": "Species", "dc:description": "The species of the tree.", "datatype": "string" }, { "name": "trim_cycle", "titles": "Trim Cycle", "dc:description": "The operation performed on the tree.", "datatype": "string", "lang": "en" }, { "name": "dbh", "titles": "Diameter at Breast Ht", "dc:description": "Diameter at Breast Height (DBH) of the tree (in feet), measured 4.5ft above ground.", "datatype": "integer" }, { "name": "inventory_date", "titles": "Inventory Date", "dc:description": "The date of the operation that was performed.", "datatype": {"base": "date", "format": "M/d/yyyy"} }, { "name": "comments", "titles": "Comments", "dc:description": "Supplementary comments relating to the operation or tree.", "datatype": "string", "separator": ";" }, { "name": "protected", "titles": "Protected", "dc:description": "Indication (YES / NO) whether the tree is subject to a protection order.", "datatype": {"base": "boolean", "format": "YES|NO"}, "default": "NO" }, { "name": "kml", "titles": "KML", "dc:description": "KML-encoded description of tree location.", "datatype": "xml" }], "primaryKey": "GID", "aboutUrl": "http://example.org/tree-ops-ext#gid-{GID}" } }
The notes annotation in the metadata description uses the Open Annotation data model currently under development within the Web Annotations Working Group. This is purely illustrative; no constraints are placed on the value of the notes annotation.
The annotated table generated from parsing the tabular data file and associated metadata is shown below and provides the basis for the conversion to JSON.
Core annotations for the resulting table T, with 9 columns and 3 rows, are shown below:
id | core annotations | ||||
---|---|---|---|---|---|
id | url | columns | rows | notes | |
T | <http://example.org/tree-ops-ext> | http://example.org/tree-ops-ext.csv | C1, C2, C3, C4, C5, C6, C7, C8, C9 | R1, R2, R3 | [{ "@type": "oa:Annotation", ... }] |
Non-core annotations for the table T are:
dc:title
"Tree Operations"
dcat:keyword
["tree", "street", "maintenance"]
dc:publisher
[{ "schema:name": "Example Municipality", "schema:url": { "@id": "http://example.org" } }]
dc:license
{ "@id": "http://opendefinition.org/licenses/cc-by/" }
dc:modified
"2010-12-31"
The value of the notes annotation has been shortened for clarity in the table above.
Annotations for the columns, rows and cells in table T are shown in the tables below:
Column annotations:
id | core annotations | annotations | |||||||
---|---|---|---|---|---|---|---|---|---|
table | number | source number | cells | name | titles | required | suppress output | dc:description | |
C1 | T | 1 | 1 | C1.1, C2.1, C3.1 | GID | GID , Generic Identifier | true | true | An identifier for the operation on a tree. |
C2 | T | 2 | 2 | C1.2, C2.2, C3.2 | on_street | On Street | The street that the tree is on. | ||
C3 | T | 3 | 3 | C1.3, C2.3, C3.3 | species | Species | The species of the tree. | ||
C4 | T | 4 | 4 | C1.4, C2.4, C3.4 | trim_cycle | Trim Cycle | The operation performed on the tree. | ||
C5 | T | 5 | 5 | C1.5, C2.5, C3.5 | dbh | Diameter at Breast Ht | Diameter at Breast Height (DBH) of the tree (in feet), measured 4.5ft above ground. | ||
C6 | T | 6 | 6 | C1.6, C2.6, C3.6 | inventory_date | Inventory Date | The date of the operation that was performed. | ||
C7 | T | 7 | 7 | C1.7, C2.7, C3.7 | comments | Comments | Supplementary comments relating to the operation or tree. | ||
C8 | T | 8 | 8 | C1.8, C2.8, C3.8 | protected | Protected | Indication (YES / NO) whether the tree is subject to a protection order. | ||
C9 | T | 9 | 9 | C1.9, C2.9, C3.9 | kml | KML | KML-encoded description of tree location. |
In this example, output for column C1 (GID
) is not required; note the suppress output annotation on this column.
Row annotations:
id | core annotations | ||||
---|---|---|---|---|---|
table | number | source number | cells | primary key | |
R1 | T | 1 | 2 | C1.1, C1.2, C1.3, C1.4, C1.5, C1.6, C1.7, C1.8, C1.9 | C1.1 |
R2 | T | 2 | 3 | C2.1, C2.2, C2.3, C2.4, C2.5, C2.6, C2.7, C2.8, C2.9 | C2.1 |
R3 | T | 3 | 4 | C3.1, C3.2, C3.3, C3.4, C3.5, C3.6, C3.7, C3.8, C3.9 | C3.1 |
Cell annotations:
id | core annotations | |||||
---|---|---|---|---|---|---|
table | column | row | string value | value | about URL | |
C1.1 | T | C1 | R1 | "1" | "1" | http://example.org/tree-ops-ext#gid-1 |
C1.2 | T | C2 | R1 | "ADDISON AV" | "ADDISON AV" | <http://example.org/tree-ops-ext#gid-1> |
C1.3 | T | C3 | R1 | "Celtis australis" | "Celtis australis" | <http://example.org/tree-ops-ext#gid-1> |
C1.4 | T | C4 | R1 | "Large Tree Routine Prune" | "Large Tree Routine Prune" (English) | <http://example.org/tree-ops-ext#gid-1> |
C1.5 | T | C5 | R1 | "11" | 11 | <http://example.org/tree-ops-ext#gid-1> |
C1.6 | T | C6 | R1 | "10/18/2010" | 2010-10-18 | <http://example.org/tree-ops-ext#gid-1> |
C1.7 | T | C7 | R1 | "" | null | <http://example.org/tree-ops-ext#gid-1> |
C1.8 | T | C8 | R1 | "" | false | <http://example.org/tree-ops-ext#gid-1> |
C1.9 | T | C9 | R1 | "<Point><coordinates>-122.156485,37.440963</coordinates></Point>" | "<Point><coordinates>-122.156485,37.440963</coordinates></Point>" (XML) | <http://example.org/tree-ops-ext#gid-1> |
C2.1 | T | C1 | R2 | "2" | "2" | <http://example.org/tree-ops-ext#gid-2> |
C2.2 | T | C2 | R2 | "EMERSON ST" | "EMERSON ST" | <http://example.org/tree-ops-ext#gid-2> |
C2.3 | T | C3 | R2 | "Liquidambar styraciflua" | "Liquidambar styraciflua" | <http://example.org/tree-ops-ext#gid-2> |
C2.4 | T | C4 | R2 | "Large Tree Routine Prune" | "Large Tree Routine Prune" (English) | <http://example.org/tree-ops-ext#gid-2> |
C2.5 | T | C5 | R2 | "11" | 11 | <http://example.org/tree-ops-ext#gid-2> |
C2.6 | T | C6 | R2 | "6/2/2010" | 2010-06-02 | <http://example.org/tree-ops-ext#gid-2> |
C2.7 | T | C7 | R2 | "" | null | <http://example.org/tree-ops-ext#gid-2> |
C2.8 | T | C8 | R2 | "" | false | <http://example.org/tree-ops-ext#gid-2> |
C2.9 | T | C9 | R2 | "<Point><coordinates>-122.156749,37.440958</coordinates></Point>" | "<Point><coordinates>-122.156749,37.440958</coordinates></Point>" (XML) | <http://example.org/tree-ops-ext#gid-2> |
C3.1 | T | C1 | R3 | "6" | "6" | <http://example.org/tree-ops-ext#gid-6> |
C3.2 | T | C2 | R3 | "ADDISON AV" | "ADDISON AV" | <http://example.org/tree-ops-ext#gid-6> |
C3.3 | T | C3 | R3 | "Robinia pseudoacacia" | "Robinia pseudoacacia" | <http://example.org/tree-ops-ext#gid-6> |
C3.4 | T | C4 | R3 | "Large Tree Routine Prune" | "Large Tree Routine Prune" (English) | <http://example.org/tree-ops-ext#gid-6> |
C3.5 | T | C5 | R3 | "29" | 29 | <http://example.org/tree-ops-ext#gid-6> |
C3.6 | T | C6 | R3 | "6/1/2010" | 2010-06-01 | <http://example.org/tree-ops-ext#gid-6> |
C3.7 | T | C7 | R3 | "cavity or decay; trunk decay; codominant leaders; included bark; large leader or limb decay; previous failure root damage; root decay; beware of BEES" | "cavity or decay" , "trunk decay" , "codominant leaders" , "included bark" , "large leader or limb decay" , "previous failure root damage" , "root decay" , "beware of BEES" | <http://example.org/tree-ops-ext#gid-6> |
C3.8 | T | C8 | R3 | "YES" | true | <http://example.org/tree-ops-ext#gid-6> |
C3.9 | T | C9 | R3 | "<Point><coordinates>-122.156299,37.441151</coordinates></Point>" | "<Point><coordinates>-122.156299,37.441151</coordinates></Point>" (XML) | <http://example.org/tree-ops-ext#gid-6> |
Minimal mode output for this example is provided below:
[{ "@id": "http://example.org/tree-ops-ext#gid-1", "on_street": "ADDISON AV", "species": "Celtis australis", "trim_cycle": "Large Tree Routine Prune", "dbh": 11, "inventory_date": "2010-10-18", "protected": false, "kml": "<Point><coordinates>-122.156485,37.440963</coordinates></Point>" }, { "@id": "http://example.org/tree-ops-ext#gid-2", "on_street": "EMERSON ST", "species": "Liquidambar styraciflua", "trim_cycle": "Large Tree Routine Prune", "dbh": 11, "inventory_date": "2010-06-02", "protected": false, "kml": "<Point><coordinates>-122.156749,37.440958</coordinates></Point>" }, { "@id": "http://example.org/tree-ops-ext#gid-6", "on_street": "ADDISON AV", "species": "Robinia pseudoacacia", "trim_cycle": "Large Tree Routine Prune", "dbh": 29, "inventory_date": "2010-06-01", "comments": [ "cavity or decay", "trunk decay", "codominant leaders", "included bark", "large leader or limb decay", "previous failure root damage", "root decay", "beware of BEES" ], "protected": true, "kml": "<Point><coordinates>-122.156299,37.441151</coordinates></Point>" }]
The subject described by each row is explicitly defined using the about URL annotation; e.g. the subject of row R1 is http://example.org/tree-ops-ext#gid-1
.
Output for column C1 ({ "name": "GID" }
) is not included as column suppress output annotation is true
.
Cells C1.7 and C2.7 (rows R1 and R2; column, { "name": "comments" }
) have null
values - no output is included for these cells.
Cell C3.7 (row R3; column, { "name": "comments" }
) contains a sequence of values; the set of values are included in an array.
Standard mode output for this example is provided below:
{ "tables": [{ "@id": "http://example.org/tree-ops-ext", "url": "http://example.org/tree-ops-ext.csv", "dc:title": "Tree Operations", "dcat:keyword": [ "tree", "street", "maintenance" ], "dc:publisher": [{ "schema:name": "Example Municipality", "schema:url": "http://example.org" }], "dc:license": "http://opendefinition.org/licenses/cc-by/", "dc:modified": "2010-12-31", "notes": [{ "@type": "oa:Annotation", "oa:hasTarget": "http://example.org/tree-ops-ext", "oa:hasBody": { "@type": "oa:EmbeddedContent", "rdf:value": "This is a very interesting comment about the table; it's a table!", "dc:format": "text/plain" } }], "row": [{ "url": "http://example.org/tree-ops-ext.csv#row=2", "rownum": 1, "describes": [{ "@id": "http://example.org/tree-ops-ext#gid-1", "on_street": "ADDISON AV", "species": "Celtis australis", "trim_cycle": "Large Tree Routine Prune", "dbh": 11, "inventory_date": "2010-10-18", "protected": false, "kml": "<Point><coordinates>-122.156485,37.440963</coordinates></Point>" }] }, { "url": "http://example.org/tree-ops-ext.csv#row=3", "rownum": 2, "describes": [{ "@id": "http://example.org/tree-ops-ext#gid-2", "on_street": "EMERSON ST", "species": "Liquidambar styraciflua", "trim_cycle": "Large Tree Routine Prune", "dbh": 11, "inventory_date": "2010-06-02", "protected": false, "kml": "<Point><coordinates>-122.156749,37.440958</coordinates></Point>" }] }, { "url": "http://example.org/tree-ops-ext.csv#row=4", "rownum": 3, "describes": [{ "@id": "http://example.org/tree-ops-ext#gid-6", "on_street": "ADDISON AV", "species": "Robinia pseudoacacia", "trim_cycle": "Large Tree Routine Prune", "dbh": 29, "inventory_date": "2010-06-01", "comments": [ "cavity or decay", "trunk decay", "codominant leaders", "included bark", "large leader or limb decay", "previous failure root damage", "root decay", "beware of BEES" ], "protected": true, "kml": "<Point><coordinates>-122.156299,37.441151</coordinates></Point>" }] }] }] }
Table T ({ "url": "http://example.org/tree-ops-ext.csv"}
) has been explicitly identified: { "@id": "<http://exmple.org/tree-ops-ext>"}
.
Non-core annotations and notes specified for table T ({ "url": "http://example.org/tree-ops-ext.csv"}
) are included in the output.
This example uses a single annotated table describing a listing of music events. Each row from the tabular data file corresponds to three resources; the music event itself, the location where that event occurs and the offer to sell tickets for that event. The goal is to convert the CSV content into schema.org markup that a search engine such as Google can use to index music events. Details of how Google expects this information to be structured can be found here.
The input tabular data file, published at http://example.org/events-listing.csv
, and the associated metadata description http://example.org/events-listing.csv-metadata.json
are provided below:
Name, Start Date, Location Name, Location Address, Ticket Url B.B. King,2014-04-12T19:30,"Lupo’s Heartbreak Hotel","79 Washington St., Providence, RI",https://www.etix.com/ticket/1771656 B.B. King,2014-04-13T20:00,"Lynn Auditorium","Lynn, MA, 01901",http://frontgatetickets.com/venue.php?id=11766
{ "@context": ["http://www.w3.org/ns/csvw", {"@language": "en"}], "url": "events-listing.csv", "dialect": {"trim": true}, "tableSchema": { "columns": [{ "name": "name", "titles": "Name", "aboutUrl": "#event-{_row}", "propertyUrl": "schema:name" }, { "name": "start_date", "titles": "Start Date", "datatype": { "base": "datetime", "format": "yyyy-MM-ddTHH:mm" }, "aboutUrl": "#event-{_row}", "propertyUrl": "schema:startDate" }, { "name": "location_name", "titles": "Location Name", "aboutUrl": "#place-{_row}", "propertyUrl": "schema:name" }, { "name": "location_address", "titles": "Location Address", "aboutUrl": "#place-{_row}", "propertyUrl": "schema:address" }, { "name": "ticket_url", "titles": "Ticket Url", "datatype": "anyURI", "aboutUrl": "#offer-{_row}", "propertyUrl": "schema:url" }, { "name": "type_event", "virtual": true, "aboutUrl": "#event-{_row}", "propertyUrl": "rdf:type", "valueUrl": "schema:MusicEvent" }, { "name": "type_place", "virtual": true, "aboutUrl": "#place-{_row}", "propertyUrl": "rdf:type", "valueUrl": "schema:Place" }, { "name": "type_offer", "virtual": true, "aboutUrl": "#offer-{_row}", "propertyUrl": "rdf:type", "valueUrl": "schema:Offer" }, { "name": "location", "virtual": true, "aboutUrl": "#event-{_row}", "propertyUrl": "schema:location", "valueUrl": "#place-{_row}" }, { "name": "offers", "virtual": true, "aboutUrl": "#event-{_row}", "propertyUrl": "schema:offers", "valueUrl": "#offer-{_row}" }] } }
The CSV to JSON translation is limited to providing one statement, or triple, per column in the table. The target schema.org markup requires 10 statements to describe each event. As the base tabular data file contains 5 columns, an additional 5 virtual columns have been added in order to provide for the full complement of statements—including the relationships between the 3 resources (event, location, and offer) described by each row of the table. Note that the virtual annotation is true
for these virtual columns.
Furthermore, note that no attempt is made to reconcile between locations or offers that may be associated with more than one event; every row in the table will create both a new location resource and offer resource in addition to the event resource. If considered necessary, applications such as OpenRefine may be used to identify and reconcile duplicate location resources once the JSON output has been generated.
The annotated table generated from parsing the tabular data file and associated metadata is shown below and provides the basis for the conversion to JSON.
Annotations for the resulting table T, with 10 columns and 2 rows, are shown below:
id | core annotations | ||
---|---|---|---|
url | columns | rows | |
T | http://example.org/events-listing.csv | C1, C2, C3, C4, C5, C6, C7, C8, C9, C10 | R1, R2 |
Annotations for the columns, rows and cells in table T are shown in the tables below:
Column annotations:
id | core annotations | ||||||
---|---|---|---|---|---|---|---|
table | number | source number | cells | name | titles | virtual | |
C1 | T | 1 | 1 | C1.1, C2.1 | name | Name | |
C2 | T | 2 | 2 | C1.2, C2.2 | start_date | Start Date | |
C3 | T | 3 | 3 | C1.3, C2.3 | location_name | Location Name | |
C4 | T | 4 | 4 | C1.4, C2.4 | location_address | Location Address | |
C5 | T | 5 | 5 | C1.5, C2.5 | ticket_url | Ticket Url | |
C6 | T | 6 | 6 | C1.6, C2.6 | type_event | true | |
C7 | T | 7 | 7 | C1.7, C2.7 | type_place | true | |
C8 | T | 8 | 8 | C1.8, C2.8 | type_offer | true | |
C9 | T | 9 | 9 | C1.9, C2.9 | location | true | |
C10 | T | 10 | 10 | C1.10, C2.10 | offers | true |
Row annotations:
id | core annotations | |||
---|---|---|---|---|
table | number | source number | cells | |
R1 | T | 1 | 2 | C1.1, C1.2, C1.3, C1.4, C1.5, C1.6, C1.7, C1.8, C1.9, C1.10 |
R2 | T | 2 | 3 | C2.1, C2.2, C2.3, C2.4, C2.5, C2.6, C2.7, C2.8, C2.9, C2.10 |
Cell annotations:
id | core annotations | |||||||
---|---|---|---|---|---|---|---|---|
table | column | row | string value | value | about URL | property URL | value URL | |
C1.1 | T | C1 | R1 | "B.B. King" | "B.B. King" | <http://example.org/events-listing.csv#event-1> | schema:name | |
C1.2 | T | C2 | R1 | "2014-04-12T19:30" | 2014-04-12T19:30:00 | <http://example.org/events-listing.csv#event-1> | schema:startDate | |
C1.3 | T | C3 | R1 | "Lupo’s Heartbreak Hotel" | "Lupo’s Heartbreak Hotel" | <http://example.org/events-listing.csv#place-1> | schema:name | |
C1.4 | T | C4 | R1 | "79 Washington St., Providence, RI" | "79 Washington St., Providence, RI" | <http://example.org/events-listing.csv#place-1> | schema:address | |
C1.5 | T | C5 | R1 | "https://www.etix.com/ticket/1771656" | <https://www.etix.com/ticket/1771656> | <http://example.org/events-listing.csv#offer-1> | schema:url | |
C1.6 | T | C6 | R1 | "" | null | <http://example.org/events-listing.csv#event-1> | rdf:type | schema:MusicEvent |
C1.7 | T | C7 | R1 | "" | null | <http://example.org/events-listing.csv#place-1> | rdf:type | schema:Place |
C1.8 | T | C8 | R1 | "" | null | <http://example.org/events-listing.csv#offer-1> | rdf:type | schema:Offer |
C1.9 | T | C9 | R1 | "" | null | <http://example.org/events-listing.csv#event-1> | schema:location | <http://example.org/events-listing.csv#place-1> |
C1.10 | T | C10 | R1 | "" | null | <http://example.org/events-listing.csv#event-1> | schema:offers | <http://example.org/events-listing.csv#offer-1> |
C2.1 | T | C1 | R2 | "B.B. King" | "B.B. King" | <http://example.org/events-listing.csv#event-2> | schema:name | |
C2.2 | T | C2 | R2 | "2014-04-13T20:00" | 2014-04-13T20:00:00 | <http://example.org/events-listing.csv#event-2> | schema:startDate | |
C2.3 | T | C3 | R2 | "Lynn Auditorium" | "Lynn Auditorium" | <http://example.org/events-listing.csv#place-2> | schema:name | |
C2.4 | T | C4 | R2 | "Lynn, MA, 01901" | "Lynn, MA, 01901" | <http://example.org/events-listing.csv#place-2> | schema:address | |
C2.5 | T | C5 | R2 | "http://frontgatetickets.com/venue.php?id=11766" | <http://frontgatetickets.com/venue.php?id=11766> | <http://example.org/events-listing.csv#offer-2> | schema:url | |
C2.6 | T | C6 | R2 | "" | null | <http://example.org/events-listing.csv#event-2> | rdf:type | schema:MusicEvent |
C2.7 | T | C7 | R2 | "" | null | <http://example.org/events-listing.csv#place-2> | rdf:type | schema:Place |
C2.8 | T | C8 | R2 | "" | null | <http://example.org/events-listing.csv#offer-2> | rdf:type | schema:Offer |
C2.9 | T | C9 | R2 | "" | null | <http://example.org/events-listing.csv#event-2> | schema:location | <http://example.org/events-listing.csv#place-2> |
C2.10 | T | C10 | R2 | "" | null | <http://example.org/events-listing.csv#event-2> | schema:offers | <http://example.org/events-listing.csv#offer-2> |
Minimal mode output for this example is provided below:
[{ "@id": "http://example.org/events-listing.csv#event-1", "@type": "schema:MusicEvent", "schema:name": "B.B. King", "schema:startDate": "2014-04-12T19:30:00", "schema:location": { "@id": "http://example.org/events-listing.csv#place-1", "@type": "schema:Place", "schema:name": "Lupo’s Heartbreak Hotel", "schema:address": "79 Washington St., Providence, RI" }, "schema:offer": { "@id": "http://example.org/events-listing.csv#offer-1", "@type": "schema:Offer", "schema:offer": "https://www.etix.com/ticket/1771656" } }, { "@id": "http://example.org/events-listing.csv#event-2", "@type": "schema:MusicEvent", "schema:name": "B.B. King", "schema:startDate": "2014-04-13T20:00:00", "schema:location": { "@id": "http://example.org/events-listing.csv#place-2", "@type": "schema:Place", "schema:name": "Lynn Auditorium", "schema:address": "Lynn, MA, 01901" }, "schema:offer": { "@id": "http://example.org/events-listing.csv#offer-2", "@type": "schema:Offer", "schema:offer": "http://frontgatetickets.com/venue.php?id=11766" } }]
Three resources are defined for each row within the table; event, location and offer. Therefore three objects are created for each row.
Each column description explicitly defines both aboutUrl
and propertyUrl
properties which are used to create the about URL and property URL annotations on the column's cells.
Columns C6, C7 and C8 ({ "name": "type_event"}
, { "name": "type_place"}
and { "name": "type_offer"}
) define the semantic types of the resources described by each row: schema:MusicEvent
, schema:Place
and schema:Offer
respectively—noting that the use of rdf:type
is converted to the name @type
(as used in [json-ld]) by this conversion application.
Column C9 ({ "name": "location"}
) uses the about URL, property URL and value URL to assert the relationship between the event and location resources.
Column C10 ({ "name": "offer"}
) uses the about URL, property URL and value URL to assert the relationship between the event and offer resources.
Standard mode output for this example is provided below:
{ "tables": [{ "url": "http://example.org/events-listing.csv", "row": [{ "url": "http://example.org/events-listing.csv#row=2", "rownum": 1, "describes": [{ "@id": "http://example.org/events-listing.csv#event-1", "@type": "schema:MusicEvent", "schema:name": "B.B. King", "schema:startDate": "2014-04-12T19:30:00", "schema:location": { "@id": "http://example.org/events-listing.csv#place-1", "@type": "schema:Place", "schema:name": "Lupo’s Heartbreak Hotel", "schema:address": "79 Washington St., Providence, RI" }, "schema:offers": { "@id": "http://example.org/events-listing.csv#offer-1", "@type": "schema:Offer", "schema:url": "https://www.etix.com/ticket/1771656" } }] }, { "url": "http://example.org/events-listing.csv#row=3", "rownum": 2, "describes": [{ "@id": "http://example.org/events-listing.csv#event-2", "@type": "schema:MusicEvent", "schema:name": "B.B. King", "schema:startDate": "2014-04-13T20:00:00", "schema:location": { "@id": "http://example.org/events-listing.csv#place-2", "@type": "schema:Place", "schema:name": "Lynn Auditorium", "schema:address": "Lynn, MA, 01901" }, "schema:offers": { "@id": "http://example.org/events-listing.csv#offer-2", "@type": "schema:Offer", "schema:url": "http://frontgatetickets.com/venue.php?id=11766" } }] }] }] }
The resources described by each row are explicitly defined using the about URL annotation—in this case three resources per row (event, location, and offer). The objects containing the name-values pairs associated with the cell values of a row are related to the object for each subject in that row using the name-value pair with name describes
.
This example is based on Use Case #4 - Publication of public sector roles and salaries and uses four annotated tables published as a group of tables. Information about senior roles and junior roles within a government department or organization are published in CSV format by each department. These are validated against a centrally published schema to ensure that all the data published by departments is consistent. Additionally, lists of organizations and professions are also published centrally, providing controlled vocabularies against which departmental submissions are validated.
Information published about junior and senior roles provides summary information for each post within the government department or organization. Whilst the junior role information is anonymous, providing only an indication of the number of full-time-equivalent (FTE) staff occupying a given post, the senior role information specifies the named individual occupying each post. As such, each row from the tabular data file describing senior roles corresponds to two resources; the post and the person occupying that post.
This example is concerned only with converting the information provided by each government department or organization rather than the centrally published information listing organizations and professions.
The input tabular data files and associated metadata descriptions are provided below:
Organization Unique Reference,Organization Name,Department Reference hefce.ac.uk,Higher Education Funding Council for England,bis.gov.uk bis.gov.uk,"Department for Business, Innovation and Skills",xx
Profession Finance Information Technology Operational Delivery Policy
Post Unique Reference,Name,Grade,Job Title,Reports to Senior Post,Profession,Organization Reference 90115,Steve Egan,SCS1A,Deputy Chief Executive,90334,Finance,hefce.ac.uk 90334,Sir Alan Langlands,SCS4,Chief Executive,xx,Policy,hefce.ac.uk
Reporting Senior Post,Grade,Payscale Minimum (£),Payscale Maximum (£),Generic Job Title,Number of Posts (FTE),Profession,Organization Reference 90115,4,17426,20002,Administrator,8.67,Operational Delivery,hefce.ac.uk 90115,5,19546,22478,Administrator,0.5,Operational Delivery,hefce.ac.uk
{ "@type": "TableGroup", "@context": ["http://www.w3.org/ns/csvw", {"@language": "en"}], "tables": [{ "url": "gov.uk/data/organizations.csv", "tableSchema": "gov.uk/schema/organizations.json", "suppressOutput": true }, { "url": "gov.uk/data/professions.csv", "tableSchema": "gov.uk/schema/professions.json", "suppressOutput": true }, { "url": "senior-roles.csv", "tableSchema": "gov.uk/schema/senior-roles.json" }, { "url": "junior-roles.csv", "tableSchema": "gov.uk/schema/junior-roles.json" }] }
{ "@id": "http://example.org/gov.uk/schema/organizations.json", "@context": "http://www.w3.org/ns/csvw", "columns": [{ "name": "ref", "titles": "Organization Unique Reference", "datatype": "string", "required": true, "propertyUrl": "dc:identifier" }, { "name": "name", "titles": "Organization Name", "datatype": "string", "propertyUrl": "foaf:name" }, { "name": "department", "titles": "Department Reference", "datatype": "string", "null": "xx", "propertyUrl": "org:subOrganizationOf", "valueUrl": "http://example.org/organization/{department}" }], "primaryKey": "ref", "aboutUrl": "http://example.org/organization/{ref}", "foreignKeys": [{ "columnReference": "department", "reference": { "schemaReference": "http://example.org/gov.uk/schema/organizations.json", "columnReference": "ref" } }] }
{ "@id": "http://example.org/gov.uk/schema/professions.json", "@context": "http://www.w3.org/ns/csvw", "columns": [{ "name": "name", "titles": "Profession", "datatype": "string", "required": true }], "primaryKey": "name" }
{ "@id": "http://example.org/gov.uk/schema/senior-roles.json", "@context": "http://www.w3.org/ns/csvw", "columns": [{ "name": "ref", "titles": "Post Unique Reference", "datatype": "string", "required": true, "propertyUrl": "dc:identifier" }, { "name": "name", "titles": "Name", "datatype": "string", "aboutUrl": "http://example.org/organization/{organizationRef}/person/{_row}", "propertyUrl": "foaf:name" }, { "name": "grade", "titles": "Grade", "datatype": "string", "propertyUrl": "http://example.org/gov.uk/def/grade" }, { "name": "job", "titles": "Job Title", "datatype": "string", "propertyUrl": "http://example.org/gov.uk/def/job" }, { "name": "reportsTo", "titles": "Reports to Senior Post", "datatype": "string", "null": "xx", "propertyUrl": "org:reportsTo", "valueUrl": "http://example.org/organization/{organizationRef}/post/{reportsTo}" }, { "name": "profession", "titles": "Profession", "datatype": "string", "propertyUrl": "http://example.org/gov.uk/def/profession" }, { "name": "organizationRef", "titles": "Organization Reference", "datatype": "string", "propertyUrl": "org:postIn", "valueUrl": "http://example.org/organization/{organizationRef}", "required": true }, { "name": "post_holder", "virtual": true, "propertyUrl": "org:heldBy", "valueUrl": "http://example.org/organization/{organizationRef}/person/{_row}" }], "primaryKey": "ref", "aboutUrl": "http://example.org/organization/{organizationRef}/post/{ref}", "foreignKeys": [{ "columnReference": "reportsTo", "reference": { "schemaReference": "http://example.org/gov.uk/schema/senior-roles.json", "columnReference": "ref" } }, { "columnReference": "profession", "reference": { "schemaReference": "http://example.org/gov.uk/schema/professions.json", "columnReference": "name" } }, { "columnReference": "organizationRef", "reference": { "schemaReference": "http://example.org/gov.uk/schema/organizations.json", "columnReference": "ref" } }] }
{ "@id": "http://example.org/gov.uk/schema/junior-roles.json", "@context": "http://www.w3.org/ns/csvw", "columns": [{ "name": "reportsToSenior", "titles": "Reporting Senior Post", "datatype": "string", "propertyUrl": "org:reportsTo", "valueUrl": "http://example.org/organization/{organizationRef}/post/{reportsToSenior}", "required": true }, { "name": "grade", "titles": "Grade", "datatype": "string", "propertyUrl": "http://example.org/gov.uk/def/grade" }, { "name": "min_pay", "titles": "Payscale Minimum (£)", "datatype": "integer", "propertyUrl": "http://example.org/gov.uk/def/min_pay" }, { "name": "max_pay", "titles": "Payscale Maximum (£)", "datatype": "integer", "propertyUrl": "http://example.org/gov.uk/def/max_pay" }, { "name": "job", "titles": "Generic Job Title", "datatype": "string", "propertyUrl": "http://example.org/gov.uk/def/job" }, { "name": "number", "titles": "Number of Posts (FTE)", "datatype": "number", "propertyUrl": "http://example.org/gov.uk/def/number_of_posts" }, { "name": "profession", "titles": "Profession", "datatype": "string", "propertyUrl": "http://example.org/gov.uk/def/profession" }, { "name": "organizationRef", "titles": "Organization Reference", "datatype": "string", "propertyUrl": "org:postIn", "valueUrl": "http://example.org/organization/{organizationRef}", "required": true }], "foreignKeys": [{ "columnReference": "reportsToSenior", "reference": { "schemaReference": "http://example.org/gov.uk/schema/senior-roles.json", "columnReference": "ref" } }, { "columnReference": "profession", "reference": { "schemaReference": "http://example.org/gov.uk/schema/professions.json", "columns": "name" } }, { "columnReference": "organizationRef", "reference": { "schemaReference": "http://example.org/gov.uk/schema/organizations.json", "columns": "ref" } }] }
This example makes extensive use of the example.org
domain. As described in [RFC6761], this domain is used for illustrative examples within documentation. In reality, the resources described here with the URL path /gov.uk
would be centrally published by the UK Government at, say, the domain data.gov.uk
.
Given that these resources are centrally published with an aspiration for reuse, the schema descriptions have been factored out into separate resources. As such, the top-level metadata description resource metadata.json
simply provides the list of tables and binds each of them to the appropriate schema that is defined elsewhere.
Finally, note that because the centrally published metadata descriptions are intended to be reused across many government departments and organizations, extra consideration has been given to defining URIs for the person and post resources defined in each row of the senior roles tabular data and subsequently referenced from the junior roles tabular data. To ensure that naming clashes are avoided, the unique reference for the organization to which the person or post belongs has been included in a path segment of the identifier. For example, the URI template property aboutUrl
used to identify the senior post is specified as http://example.org/organization/{organizationRef}/post/{ref}
, thus yielding the URI http://example.org/organization/hefce.ac.uk/post/90115
for the post described in the first row of the senior roles tabular data.
The group of tables generated from parsing the tabular data files and associated metadata is shown below and provides the basis for the conversion to JSON.
Annotations for the group of tables G and the four tables Ta, Tb, Tc, and Td are shown below:
Group of Tables annotations:
id | core annotations |
---|---|
tables | |
G | Ta, Tb, Tc, Td |
Table annotations:
id | core annotations | ||||
---|---|---|---|---|---|
url | columns | rows | suppress output | foreign keys | |
Ta | http://example.org/gov.uk/data/organizations.csv | Ca1, Ca2, Ca3 | Ra1, Ra2 | true | Fa1 |
Tb | http://example.org/gov.uk/professions.csv | Cb1 | Rb1, Rb2, Rb3, Rb4 | true | |
Tc | http://example.org/senior-roles.csv | Cc1, Cc2, Cc3, Cc4, Cc5, Cc6 | Rc1, Rc2 | false | Fc1, Fc2, Fc3 |
Td | http://example.org/junior-roles.csv | Cd1, Cd2, Cd3, Cd4, Cd5, Cd6, Cd7 | Rd1, Rd2 | false | Fd1, Fd2, Fd3 |
In this example, output for the centrally published lists of organizations and professions, tables Ta and Tb (http://example.org/gov.uk/data/organizations.csv
and http://example.org/gov.uk/data/professions.csv
respectively), are not required; only information from the departmental submissions is to be translated to RDF. Note the suppress output annotation on this table.
The following foreign keys are defined:
id | columns in table | columns in referenced table |
---|---|---|
Fa1 | Ca3 | Ca1 |
Fc1 | Cc5 | Cc1 |
Fc2 | Cc6 | Cb1 |
Fc3 | Cc7 | Ca1 |
Fd1 | Cd1 | Cc1 |
Fd2 | Cd7 | Cb1 |
Fd3 | Cd8 | Ca1 |
Annotations for the columns, rows and cells in table T are shown in the tables below:
Column annotations:
id | core annotations | |||||||
---|---|---|---|---|---|---|---|---|
table | number | source number | cells | name | titles | required | virtual | |
Ca1 | Ta | 1 | 1 | Ca1.1, Ca2.1 | ref | Organization Unique Reference | true | |
Ca2 | Ta | 1 | 1 | Ca1.2, Ca2.2 | name | Organization Name | ||
Ca3 | Ta | 1 | 1 | Ca1.3, Ca2.3 | department | Department Reference | ||
Cb1 | Tb | 1 | 1 | Cb1.1, Cb2.1, Cb3.1, Cb4.1 | name | Profession | true | |
Cc1 | Tc | 1 | 1 | Cc1.1, Cc2.1 | ref | Post Unique Reference | true | |
Cc2 | Tc | 2 | 2 | Cc1.2, Cc2.2 | name | Name | ||
Cc3 | Tc | 3 | 3 | Cc1.3, Cc2.3 | grade | Grade | ||
Cc4 | Tc | 4 | 4 | Cc1.4, Cc2.4 | job | Job Title | ||
Cc5 | Tc | 5 | 5 | Cc1.5, Cc2.5 | reportsTo | Reports to Senior Post | ||
Cc6 | Tc | 6 | 6 | Cc1.6, Cc2.6 | profession | Profession | ||
Cc7 | Tc | 7 | 7 | Cc1.7, Cc2.7 | organizationRef | Organization Reference | true | |
Cc8 | Tc | 8 | 8 | Cc1.8, Cc2.8 | post_holder | true | ||
Cd1 | Td | 1 | 1 | Cd1.1, Cd2.1 | reportsToSenior | Reporting Senior Post | true | |
Cd2 | Td | 2 | 2 | Cd1.2, Cd2.2 | grade | Grade | ||
Cd3 | Td | 3 | 3 | Cd1.3, Cd2.3 | min_pay | Payscale Minimum (£) | ||
Cd4 | Td | 4 | 4 | Cd1.4, Cd2.4 | max_pay | Payscale Maximum (£) | ||
Cd5 | Td | 5 | 5 | Cd1.5, Cd2.5 | job | Generic Job Title | ||
Cd6 | Td | 6 | 6 | Cd1.6, Cd2.6 | number | Number of Posts (FTE) | ||
Cd7 | Td | 7 | 7 | Cd1.7, Cd2.7 | profession | Profession | ||
Cd8 | Td | 8 | 8 | Cd1.8, Cd2.8 | organizationRef | Organization Reference | true |
Column Cc8, with the virtual
annotation specified as true
, is used to relate the person resource, whose name is provided in column Cc2, to the associated post resource within the current row of table Tc ({ "url": "http://example.org/senior-roles.csv" }
).
Row annotations:
id | core annotations | |||
---|---|---|---|---|
table | number | source number | cells | |
Ra1 | Ta | 1 | 2 | Ca1.1, Ca1.2, Ca1.3 |
Ra2 | Ta | 2 | 3 | Ca2.1, Ca2.2, Ca2.3 |
Rb1 | Tb | 1 | 2 | Cb1.1 |
Rb2 | Tb | 2 | 3 | Cb2.1 |
Rb3 | Tb | 3 | 4 | Cb3.1 |
Rb4 | Tb | 4 | 5 | Cb4.1 |
Rc1 | Tc | 1 | 2 | Cc1.1, Cc1.2, Cc1.3, Cc1.4, Cc1.5, Cc1.6, Cc1.7, Cc1.8 |
Rc2 | Tc | 2 | 3 | Cc2.1, Cc2.2, Cc2.3, Cc2.4, Cc2.5, Cc2.6, Cc2.7, Cc2.8 |
Rd1 | Td | 1 | 2 | Cd1.1, Cd1.2, Cd1.3, Cd1.4, Cd1.5, Cd1.6, Cd1.7, Cd1.8 |
Rd2 | Td | 2 | 3 | Cd2.1, Cd2.2, Cd2.3, Cd2.4, Cd2.5, Cd2.6, Cd2.7, Cd2.8 |
Cell annotations:
id | core annotations | |||||||
---|---|---|---|---|---|---|---|---|
table | column | row | string value | value | about URL | property URL | value URL | |
Ca1.1 | Ta | Ca1 | Ra1 | "hefce.ac.uk" | "hefce.ac.uk" | <http://example.org/organization/hefce.ac.uk> | dc:identifier | |
Ca1.2 | Ta | Ca2 | Ra1 | "Higher Education Funding Council for England" | "Higher Education Funding Council for England" | <http://example.org/organization/hefce.ac.uk> | foaf:name | |
Ca1.3 | Ta | Ca3 | Ra1 | "bis.gov.uk" | "bis.gov.uk" | <http://example.org/organization/hefce.ac.uk> | org:subOrganizationOf | <http://example.org/organization/bis.gov.uk> |
Ca2.1 | Ta | Ca1 | Ra2 | "bis.gov.uk" | "bis.gov.uk" | <http://example.org/organization/bis.gov.uk> | dc:identifier | |
Ca2.2 | Ta | Ca2 | Ra2 | "Department for Business, Innovation and Skills" | "Department for Business, Innovation and Skills" | <http://example.org/organization/bis.gov.uk> | foaf:name | |
Ca2.3 | Ta | Ca3 | Ra2 | "xx" | null | <http://example.org/organization/bis.gov.uk> | org:subOrganizationOf | |
Cb1.1 | Tb | Cb1 | Rb1 | "Finance" | "Finance" | |||
Cb2.1 | Tb | Cb1 | Rb2 | "Information Technology" | "Information Techology" | |||
Cb3.1 | Tb | Cb1 | Rb3 | "Operational Delivery" | "Operational Delivery" | |||
Cb4.1 | Tb | Cb1 | Rb4 | "Policy" | "Policy" | |||
Cc1.1 | Tc | Cc1 | Rc1 | "90115" | "90115" | <http://example.org/organization/hefce.ac.uk/post/90115> | dc:identifier | |
Cc1.2 | Tc | Cc2 | Rc1 | "Steve Egan" | "Steve Egan" | <http://example.org/organization/hefce.ac.uk/person/1> | foaf:name | |
Cc1.3 | Tc | Cc3 | Rc1 | "SCS1A" | "SCS1A" | <http://example.org/organization/hefce.ac.uk/post/90115> | <http://example.org/gov.uk/def/grade> | |
Cc1.4 | Tc | Cc4 | Rc1 | "Deputy Chief Executive" | "Deputy Chief Executive" | <http://example.org/organization/hefce.ac.uk/post/90115> | <http://example.org/gov.uk/def/job> | |
Cc1.5 | Tc | Cc5 | Rc1 | "90334" | "90334" | <http://example.org/organization/hefce.ac.uk/post/90115> | org:reportsTo | <http://example.org/organization/hefce.ac.uk/post/90334> |
Cc1.6 | Tc | Cc6 | Rc1 | "Finance" | "Finance" | <http://example.org/organization/hefce.ac.uk/post/90115> | <http://example.org/gov.uk/def/profession> | |
Cc1.7 | Tc | Cc7 | Rc1 | "hefce.ac.uk" | "hefce.ac.uk" | <http://example.org/organization/hefce.ac.uk/post/90115> | org:postIn | <http://example.org/organization/hefce.ac.uk> |
Cc1.8 | Tc | Cc8 | Rc1 | "" | null | <http://example.org/organization/hefce.ac.uk/post/90115> | org:heldBy | <http://example.org/organization/hefce.ac.uk/person/1> |
Cc2.1 | Tc | Cc1 | Rc2 | "90334" | "90334" | <http://example.org/organization/hefce.ac.uk/post/90334> | dc:identifier | |
Cc2.2 | Tc | Cc2 | Rc2 | "Sir Alan Langlands" | "Sir Alan Langlands" | <http://example.org/organization/hefce.ac.uk/person/2> | foaf:name | |
Cc2.3 | Tc | Cc3 | Rc2 | "SCS4" | "SCS4" | <http://example.org/organization/hefce.ac.uk/post/90334> | <http://example.org/gov.uk/def/grade> | |
Cc2.4 | Tc | Cc4 | Rc2 | "Chief Executive" | "Chief Executive" | <http://example.org/organization/hefce.ac.uk/post/90334> | <http://example.org/gov.uk/def/job> | |
Cc2.5 | Tc | Cc5 | Rc2 | "xx" | null | <http://example.org/organization/hefce.ac.uk/post/90334> | org:reportsTo | |
Cc2.6 | Tc | Cc6 | Rc2 | "Policy" | "Policy" | <http://example.org/organization/hefce.ac.uk/post/90334> | <http://example.org/gov.uk/def/profession> | |
Cc2.7 | Tc | Cc7 | Rc2 | "hefce.ac.uk" | "hefce.ac.uk" | <http://example.org/organization/hefce.ac.uk/post/90334> | org:postIn | <http://example.org/organization/hefce.ac.uk> |
Cc2.8 | Tc | Cc8 | Rc2 | "" | null | <http://example.org/organization/hefce.ac.uk/post/90334> | org:heldBy | <http://example.org/organization/hefce.ac.uk/person/2> |
Cd1.1 | Td | Cd1 | Rd1 | "90115" | "90115" | org:reportsTo | <http://example.org/organization/hefce.ac.uk/post/90115> | |
Cd1.2 | Td | Cd2 | Rd1 | "4" | "4" | <http://example.org/gov.uk/def/grade> | ||
Cd1.3 | Td | Cd3 | Rd1 | "17426" | 17426 | <http://example.org/gov.uk/def/min_pay> | ||
Cd1.4 | Td | Cd4 | Rd1 | "20002" | 20002 | <http://example.org/gov.uk/def/max_pay> | ||
Cd1.5 | Td | Cd5 | Rd1 | "Administrator" | "Administrator" | <http://example.org/gov.uk/def/job> | ||
Cd1.6 | Td | Cd6 | Rd1 | "8.67" | 8.67 | <http://example.org/gov.uk/def/number_of_posts> | ||
Cd1.7 | Td | Cd7 | Rd1 | "Operational Delivery" | "Operational Delivery" | <http://example.org/gov.uk/def/profession> | ||
Cd1.8 | Td | Cd8 | Rd1 | "hefce.ac.uk" | "hefce.ac.uk" | org:postIn | <http://example.org/organization/hefce.ac.uk> | |
Cd2.1 | Td | Cd1 | Rd2 | "90115" | "90115" | org:reportsTo | <http://example.org/organization/hefce.ac.uk/post/90115> | |
Cd2.2 | Td | Cd2 | Rd2 | "5" | "5" | <http://example.org/gov.uk/def/grade> | ||
Cd2.3 | Td | Cd3 | Rd2 | "19546" | 19546 | <http://example.org/gov.uk/def/min_pay> | ||
Cd2.4 | Td | Cd4 | Rd2 | "22478" | 22478 | <http://example.org/gov.uk/def/max_pay> | ||
Cd2.5 | Td | Cd5 | Rd2 | "Administrator" | "Administrator" | <http://example.org/gov.uk/def/job> | ||
Cd2.6 | Td | Cd6 | Rd2 | "0.5" | 0.5 | <http://example.org/gov.uk/def/number_of_posts> | ||
Cd2.7 | Td | Cd7 | Rd2 | "Operational Delivery" | "Operational Delivery" | <http://example.org/gov.uk/def/profession> | ||
Cd2.8 | Td | Cd8 | Rd2 | "hefce.ac.uk" | "hefce.ac.uk" | org:postIn | <http://example.org/organization/hefce.ac.uk> |
Notice that value URL is not specified for cells Ca2.3 and Cc2.5 because in each case the cell value is null
and the virtual annotation of column Cb5 is not defined.
Minimal mode output for this example is provided below:
[{ "@id": "http://example.org/organization/hefce.ac.uk/post/90115", "dc:identifier": "90115", "org:heldBy": { "@id": "http://example.org/organization/hefce.ac.uk/person/1", "foaf:name": "Steve Egan" }, "http://example.org/gov.uk/def/grade": "SCS1A", "http://example.org/gov.uk/def/job": "Deputy Chief Executive", "org:reportsTo": "http://example.org/organization/hefce.ac.uk/post/90334", "http://example.org/gov.uk/def/profession": "Finance", "org:postIn": "http://example.org/organization/hefce.ac.uk" }, { "@id": "http://example.org/organization/hefce.ac.uk/post/90334", "dc:identifier": "90334", "org:heldBy": { "@id": "http://example.org/organization/hefce.ac.uk/person/2", "foaf:name": "Sir Alan Langlands" }, "http://example.org/gov.uk/def/grade": "SCS4", "http://example.org/gov.uk/def/job": "Chief Executive", "http://example.org/gov.uk/def/profession": "Policy", "org:postIn": "http://example.org/organization/hefce.ac.uk" }, { "org:reportsTo": "http://example.org/organization/hefce.ac.uk/post/90115", "http://example.org/gov.uk/def/grade": "4", "http://example.org/gov.uk/def/min_pay": 17426, "http://example.org/gov.uk/def/max_pay": 20002, "http://example.org/gov.uk/def/job": "Administrator", "http://example.org/gov.uk/def/number_of_posts": 8.67, "http://example.org/gov.uk/def/profession": "Operational Delivery", "org:postIn": "http://example.org/organization/hefce.ac.uk" }, { "org:reportsTo": "http://example.org/organization/hefce.ac.uk/post/90115", "http://example.org/gov.uk/def/grade": "5", "http://example.org/gov.uk/def/min_pay": 19546, "http://example.org/gov.uk/def/max_pay": 22478, "http://example.org/gov.uk/def/job": "Administrator", "http://example.org/gov.uk/def/number_of_posts": 0.5, "http://example.org/gov.uk/def/profession": "Operational Delivery", "org:postIn": "http://example.org/organization/hefce.ac.uk" }]
Prefixes defined within the RDFa 1.1 Initial Context ([rdfa-core]) are not expanded; e.g. dc:
for <http://purl.org/dc/terms/>.
Output for tables Ta and Tb ({ "url": "http://example.org/gov.uk/data/organizations.csv" }
and { "url": "http://example.org/gov.uk/data/professions.csv" }
) are not included as the suppress output annotation has the value true
for each of the tables.
The property URL is specified for all cells in tables Tc and Td.
Columns Cc5 and Cd1 ({ "name": "reportsTo" }
and { "name": "reportsToSenior" }
) use the about URL, property URL and value URL annotations to assert the relationship between the post described by a given row and the senior post to which it reports. However, since senior posts and junior posts are described in different tables it is not possible to create nested objects for this particular case.
Similarly, columns Cc7 and Cd8 (both with { "name": "organizationRef" }
) use the about URL, property URL and value URL annotations to assert the relationship between the post described by a given row and the organization to which it belongs.
Finally, note that two resources are created for each row within table Tc ({ "url": "http://example.org/senior-roles.csv" }
): the person and the post they occupy. The relationship between these resources is specified via virtual column Cc8 ({ "name": "post_holder" }
) using the about URL, property URL and value URL annotations. The person object provides the value of the name-value pair with corresponding name org:heldBy
, thus nesting the person object within the post object.
Standard mode output for this example is provided below:
{ "tables": [{ "url": "http://example.org/senior-roles.csv", "row": [{ "url": "http://example.org/senior-roles.csv#row=2", "rownum": 1, "describes": [{ "@id": "http://example.org/organization/hefce.ac.uk/post/90115", "dc:identifier": "90115", "org:heldBy": { "@id": "http://example.org/organization/hefce.ac.uk/person/1", "foaf:name": "Steve Egan" }, "http://example.org/gov.uk/def/grade": "SCS1A", "http://example.org/gov.uk/def/job": "Deputy Chief Executive", "org:reportsTo": "http://example.org/organization/hefce.ac.uk/post/90334", "http://example.org/gov.uk/def/profession": "Finance", "org:postIn": "http://example.org/organization/hefce.ac.uk" }] }, { "url": "http://example.org/senior-roles.csv#row=3", "rownum": 2, "describes": [{ "@id": "http://example.org/organization/hefce.ac.uk/post/90334", "dc:identifier": "90334", "org:heldBy": { "@id": "http://example.org/organization/hefce.ac.uk/person/2", "foaf:name": "Sir Alan Langlands" }, "http://example.org/gov.uk/def/grade": "SCS4", "http://example.org/gov.uk/def/job": "Chief Executive", "http://example.org/gov.uk/def/profession": "Policy", "org:postIn": "http://example.org/organization/hefce.ac.uk" }] }] }, { "url": "http://example.org/junior-roles.csv", "row": [{ "url": "http://example.org/junior-roles.csv#row=2", "rownum": 1, "describes": [{ "org:reportsTo": "http://example.org/organization/hefce.ac.uk/post/90115", "http://example.org/gov.uk/def/grade": "4", "http://example.org/gov.uk/def/min_pay": 17426, "http://example.org/gov.uk/def/max_pay": 20002, "http://example.org/gov.uk/def/job": "Administrator", "http://example.org/gov.uk/def/number_of_posts": 8.67, "http://example.org/gov.uk/def/profession": "Operational Delivery", "org:postIn": "http://example.org/organization/hefce.ac.uk" }] }, { "url": "http://example.org/junior-roles.csv#row=3", "rownum": 2, "describes": [{ "org:reportsTo": "http://example.org/organization/hefce.ac.uk/post/90115", "http://example.org/gov.uk/def/grade": "5", "http://example.org/gov.uk/def/min_pay": 19546, "http://example.org/gov.uk/def/max_pay": 22478, "http://example.org/gov.uk/def/job": "Administrator", "http://example.org/gov.uk/def/number_of_posts": 0.5, "http://example.org/gov.uk/def/profession": "Operational Delivery", "org:postIn": "http://example.org/organization/hefce.ac.uk" }] }] }] }
@id
annotation in the model is ignored for JSON.table
and title
properties have been changed to tables
and titles
, respectively, to be consistent in the usage of plural forms.The document has undergone substantial changes since the first public working draft. Below are some of the changes made: