Jsop
Overview
"Jsop" is the idea of a lightweight HTTP protocol for manipulating JSON-based object models.
See David Nüscheler's slides for an initial proposal.
This protocol would include
- a mapping between the JCR data model and JSON
- a notation to identify object members (this will be very similar to JCR path notation)
- a way to expose information about a tree of JCR nodes using JSON notation; if this needs to co-exist with the classical view (aka WebDAV), we either need a creative way to mint new URIs, or may have to try content negotiation
- one or more formats expression changes in a JSON structure
JCR-JSON mapping
TBD.
Identifier Notation
TBD (I believe raw JCR paths work as they subset JSON names and never need the "/"; but what about namespace prefixes? The current use is compact but doesn't necessarily yield stable identifiers )
IETF Work on Identifier Notation
Internet Draft:
- a pointer syntax for identifying objects in an object tree: http://tools.ietf.org/html/draft-ietf-appsawg-json-pointer
- note that this uses "/" as separator and escapes "/" and "~" as "~1" and "~0"
- furthermore note that it uses "arrayname/N" to address entry N of an array; I don't think we have similar functionality in JSOP
HTTP binding
It needs to be defined how JCR nodes and JCR events are mapped to HTTP URIs; this includes the name mapping, the granularity, and more.
For instance:
- handling of workspace name
- escaping non-URI characters
- do nodes and properties need to be distinguished
- namespace prefix handling
- co-existence with other protocols, such as WebDAV
- how to expose ordered collections (JavaScript object membership is not ordered)
TODO: describe the current implementation in jcr-server
Diff Formats
IETF Work on Diff Formats
Internet Draft:
- a model for patch operations and an associated syntax in JSON: http://tools.ietf.org/html/draft-ietf-appsawg-json-patch – this captures patch operations inside a JSON container (not a custom format as discussed below)
Open Issues:
- the format does not define a place for metadata
This issue has been raised as a potential enhancement on the IETF apps-discuss mailing list.
Draft Implementations: JSOP-Diff
The definitions below are based on the format used by JCR Server but diverge in some areas. This is still work in progress and definitions may change at anytime.
- Oak MicroKernel
- DavExRemoting in Jackrabbit WebDAV
Compact Syntax
// JSOP-Diff Proposal DIFFS ::= (ADD | SET | REMOVE | MOVE | COPY | TEST | METADATA | EXTENSION)* ADD ::= "+" STRING ":" OBJECT SET ::= "^" STRING ":" ATOM | ARRAY REMOVE ::= "-" STRING MOVE ::= ">" STRING ":" STRING COPY ::= "*" STRING ":" STRING TEST ::= "=" STRING ":" ATOM | ARRAY METADATA ::= "@" OBJECT EXTENSION ::= OP STRING ":" (OBJECT | ATOM | ARRAY) OP ::= /* any single character except for +, ^, -, >, *, =, @ */ // JSON (RFC 4627) OBJECT ::= "{" (PAIR ("," PAIR)*)? "}" PAIR ::= STRING ":" VALUE VALUE ::= COMPOUND | ATOM COMPOUND ::= OBJECT | ARRAY ATOM ::= STRING | NUMBER | "true" | "false" | "null" ARRAY ::= [ (VALUE ("," VALUE)*)? ] STRING ::= /* See RFC 4627, Section 2.5 */ NUMBER ::= /* See RFC 4627, Section 2.4 */
IETF ABNF variant:
diffs = *( ws ( add / set / remove / move / copy / test ) ws ) add = "+" ws pointer ws ":" ws object copy = "*" ws pointer ws ":" ws pointer move = ">" ws pointer ws ":" ws pointer remove = "-" ws pointer set = "^" ws pointer ws ":" ws ( atom / array ) ; object? test = "=" ws pointer ws ":" ws ( atom / array ) ; object? atom = string / number / false / null / true pointer = string ; JSON array = <see RFC4627, Section 2.3> false = <see RFC4627, Section 2.1> null = <see RFC4627, Section 2.1> number = <see RFC4627, Section 2.4> object = <see RFC4627, Section 2.2> string = <see RFC4627, Section 2.5> true = <see RFC4627, Section 2.1> ws = <see RFC4627, Section 2.1>
A parser, and a simple test case for this syntax is available from the sandbox.
Also available are a tokenizer, a builder, and a Jsop writer / reader. Those implementations are token based, and therefore not limited to the JSOP format described here.
Syntax
jsop:
- diff
- diff jsop
A Jsop string contains one or multiple Jsop diff lines.
diff:
- addNodeDiff
- setPropertyDiff
- removeNodeDiff
- removePropertyDiff
- moveNodeDiff
- copyNodeDiff
- testProperty
- metaData
A diff line can contain the information about adding nodes (possibly multiple nested nodes), adding a property to a node, setting a property, moving a node, or removing a node or property. There is a special metadata diff line.
addNodeDiff:
- + pathString: object
The added node may contain child nodes.
addPropertyDiff:
- + pathString: propertyValue
setPropertyDiff:
- ^ pathString: propertyValue
Modifies the value of an existing property or otherwise creates a property with the specified value.
moveNodeDiff:
- > pathString: newPathString
copyNodeDiff:
- * pathString: newPathString
removeNodeDiff:
- - pathString
removePropertyDiff:
- ^ pathString: null
Setting the value to null will remove the property.
propertyValue:
- string
- number
- array
- true
- false
A property value can be any value, except for a object itself.
testProperty:
- = pathString: { propertyValue | null }
Before applying the rest of patch, the value is verified. If it does not match, then the subsequent line(s) will not be applied. The exact semantics are not yet defined however and will most likely be implementation specific - for example it is undefined whether a mismatch will result in an exception or not, and whether all following lines of the commit belong to the same atomic operation or not. This addition allows to construct atomic commits.
metaData:
- @ object
The metadata line contains metadata about the following diff lines. Metadata typically includes the timestamp (when did the change occur), the user, the commit message. A jsop object can contain multiple metadata lines. It depends on the implementation whether or not metadata is used, and how it is used.
object:
- {}
- { members }
members:
- pair
- pair, members
pair:
- string: value
array:
[]
[elements ]
elements:
- value
- value, elements
value:
- string
- number
- object
- array
- true
- false
- null