@itentialopensource/binding-schema
v2.0.2
Published
A schema extension for JSON schema that builds upon hyper schema to dynamically bind data into a JSON schema document.
Readme
Binding Schema
A schema extension for JSON schema that builds upon JSON hyper-schema to dynamically bind data into a JSON schema document. This is the home for the binding schema specification and its official JavaScript library.
Notice
This is an early version of a JSON schema extension.
Introduction
Binding Schema is a JSON-based format for describing data binding relationships between JSON documents and hypermedia. It is an extension schema of JSON Schema and Hyper-Schema.
Motivation
Binding Schema aims to enable autonomous data binding between JSON documents and resources through a schema that aligns itself with modern web specifications & technologies. In the future, hopefully it aids in service discoverability that lead to data mutation actions.
Use-Cases
Any place that a JSON document needs to be mutated with data external that JSON document (e.g., in conjunction with react-jsonschema-forms, a dropdown needs to be populated with values that are retrieved from a REST API).
Getting Started
Currently, binding schema assumes the hypermedia of interest is exposed via a RESTful web service and responses with a JSON resource. Use the binding properties described in the specification below to define data bindings between a JSON resource and an existing JSON document.
Example
To illustrate how a binding schema definition describes the mapping between a resource to an existing JSON document, follow this simple example.
Target JSON Document:
{
"users": []
}Binding schema definition:
{
"binding:method": "GET",
"binding:link": {
"$ref": "/links",
"rel": "collection"
},
"binding:source": {
"propertyPointer": "/data",
"keyPointer": "/login"
},
"binding:target": {
"propertyPointer": "/users"
},
"binding:hyperSchema": {
"type": "object",
"base": "https://api.github.com/",
"links": [
{
"rel": "collection",
"href": "users",
"targetMediaType": "application/json",
"targetSchema": { "$ref": "#" }
}
]
}
}This binding schema definition acts as an instruction to execute a GET request to GitHub's public API at https://api.github.com/users, and bind the returned data found inside of the response's data[] -> login property to the users inside the target JSON document, which would result in a JSON document as such:
{
"users": ["usernameA", "usernameB", ...]
}Specification
Binding Schema's specification aims to align itself with existing terminology used by the JSON Schema specification.
Binding Keys
JSON keys that are prefixed with binding: belong to the binding schema specification and act as instructions for a binding definition.
Binding Definition
A binding definition contains the following properties:
- binding:method
- binding:timeout
- binding:link
- binding:body
- binding:source
- binding:target
- binding:hyperSchema
binding:method
The method for the request that needs to be performed in order to retrieve data from a RESTful web service. Supported methods:
- GET
- POST
binding:timeout
Defines a timeout for the request. If request is not returned within that time frame it will return an error.
binding:link
Describes which link inside of a binding:hyperschema definition to execute a binding with.
binding:link.$ref
A path inside of its hyper-schema definition at binding:hyperschema, in which the link relation type of interest can be found. This follows the same format as Schema Reference.
binding:link.rel
A name to identify the specific link relation to be used by a binding definition.
binding:body
(This property is conditional on binding:method)
This is the request body for a request. When binding:method is set GET, this property should not be defined; however, it is required when binding:method is set to POST.
binding:source
The source is a JSON document that contains the data to be bound to a target. The binding:source object contains properties to describe binding instructions associated with the source.
binding:source.propertyPointer
A JSON pointer that identifies the property by its key within the response data, where the source data can be found. (Often this is /data or /results.) The value of the property MUST be a valid JSON Pointer in JSON String representation form.
binding:source.keyPointer
(This property is optional)
A key that identifies the sub-property of the source data that should be mapped to the target. This is used in situation where the response data is an array of objects. The value of the property MUST be a valid JSON Pointer in JSON String representation form and is relative to the binding:source.propertyPointer location.
binding:target
The target is a JSON document to which one or more sources are bound. The binding:target object contains properties to describe binding instructions associated with the target.
binding:target.propertyPointer
A JSON pointer that identifies the property by its key within the target JSON document to which the source data should be bound. The value of the property MUST be a valid JSON Pointer in JSON String representation form.
binding:hyperSchema
Use the JSON Hyper-Schema specification to define the hypermedia of interest. Required hyper-schema properties:
Schema Structure & Nesting
Binding schemas allow defining any number of bindings on any level of an object.
For example, here is a binding schema document with three binding definitions at different levels of the JSON document.
{
"binding:method": "GET",
"binding:link": {
"$ref": "/links",
"rel": "collection"
},
"binding:source": {
"propertyPointer": "/data",
"keyPointer": "/login"
},
"binding:target": {
"propertyPointer": ""
},
"binding:hyperSchema": { ... },
"users": {
"binding:method": "GET",
"binding:link": {
"$ref": "/links",
"rel": "collection"
},
"binding:source": {
"propertyPointer": "/data",
"keyPointer": "/login"
},
"binding:target": {
"propertyPointer": ""
},
"binding:hyperSchema": { ... },
"nestedUsers": {
"binding:method": "GET",
"binding:link": {
"$ref": "/links",
"rel": "collection"
},
"binding:source": {
"propertyPointer": "/data",
"keyPointer": "/login"
},
"binding:target": {
"propertyPointer": ""
},
"binding:hyperSchema": { ... }
}
}
}Tools
The binding schema specification only describes the language of the schema, but leaves implementation details of composing a binding schema and a json document up to the developer. However, this is a great opportunity to create language-specific composer libraries. Currently, the only officially maintained binding schema composer library is the JavaScript library. External contributions are greatly welcomed.
Libraries
JavaScript
Upcoming Features of Spec:
V1
- [ ] Support authentication via link.headerSchema
- [ ] Binding meta-schema
V2
- [ ] Property dependencies for sequencing and internal/external references
- [ ] Source-to-Target data transformations
- [ ] JSON API Support?
- [ ] GraphQL Support?
- [ ] Further language support with binding schema libraries
Upcoming Features of JavaScript library:
V1
- [x] Support source.keyPointer as nested object
- [x] Support source.propertyPath as nested object
- [ ] Support target.propertyPath as nested object
- [ ] Support array usage within JSON pointers
- [ ] Support non-nested object bindings
- [x] Support keyless/non-array responses bindings
- [ ] Support authentication via link.headerSchema
- [ ] Binding schema validator
- [ ] Docs for how to use tool
- [ ] JSDocs in code
- [ ] Fix index.js unit tests
V2
- [ ] Handle property dependencies
- [ ] Handle transformations
