This protocol is designed to distribute and mutate JSON between nodes using patches that are sent via Remote Procedure Calls (RPC).
It is a thin layer on top of your data network that helps you communicate nodes using RPCs. It is also a pattern that makes easy, update, mutate or even sync the state of your system.
Is important to point out that DOP does not handle data sync or conflict resolutions. It is not a CRDT or OT protocol.
2. Patches
3. Types
// Format
[<request_id>, <function_id>, [<argument1>, <argument2>, ...]]
// Example
[1, 1, ["[email protected]", "password1234"]]-
<request_id>An integer greater than0(zero). -
<function_id>A number or string that represent the id of the function previously defined that has to be runned. -
<argument>Any value.
// Format
[-<request_id>, <response_state>, <response_value>]
// Resolve example
[-1, 0, { "name":"John Doe", "age":30 }]
// Reject example
[-1, "Invalid email"]-
<request_id>An integer lower than0(zero). Is just therequest_idused on the request but in negative. -
<response_state>If state is0(zero) means the request it has been resolved. Any other case means a rejection. -
<response_value>Can be any value. But is only defined if theresponse_valueis equal to0(zero). Which means is a valid response.
This is useful when it does not need a response. Like a push notification.
// Format
[0, <function_id>, [<argument1>, <argument2>, ...]]
// Example
[0, 1, {event: "USER_CONNECTED", data: { "nick":"Enzo","at":"30 Nov 2019 14:18:31" }}]-
<function_id>An integer that represent the id of the function previously defined that has to be runned. -
<argument>Any value.
A Patch describes changes to be made to a target JSON document using a syntax that closely mimics the document being modified. The implementation must follow all the rules defined in JSON Merge Patch specification (except one).
| ORIGINAL | PATCH | RESULT |
|---|---|---|
{"a":"b"} |
{"a":"c"} |
{"a":"c"} |
{"a":"b"} |
{"b":"c"} |
{"a":"b","b":"c"} |
{"a":"b"} |
{"a":{"$d":0}} |
{} |
{"a":"b","b":"c"} |
{"a":{"$d":0}} |
{"b":"c"} |
{"a":["b"]} |
{"a":"c"} |
{"a":"c"} |
{"a":"c"} |
{"a":["b"]} |
{"a":["b"]} |
{"a": {"b":"c"}} |
{"a":{"b":"d","c":{"$d":0}}} |
{"a": {"b":"d"}} |
{"a":[{"b":"c"}]} |
{"a": [1]} |
{"a": [1]} |
["a","b"] |
["c","d"] |
["c","d"] |
{"a":"b"} |
["c"] |
["c"] |
{"a":"foo"} |
{"a":null} |
{"a":null} |
{"a":"foo"} |
null |
null |
{"a":"foo"} |
"bar" |
"bar" |
{"e":{"$d":0}} |
{"a":1} |
{"e":{"$d":0},"a":1} |
[1,2] |
{"a":"b","c":{"$d":0}} |
{"a":"b"} |
{} |
{"a":{"bb":{"ccc":{"$d":0}}}} |
{"a":{"bb":{}}} |
{"a":{"b":"c","d":"e"}} |
{"a":{"$r":{"f":"g"}} |
{"a":{"f":"g"} |
There is one big difference between JSON Merge Patch and DOP. JSON Merge Patch uses null as an instruction to delete properties, while in DOP we leave null as it is.
DOP incorporates special types that can extend the basic instructions. For example, if we want to delete properties we would use {"$d":0}.
Examples
// Original
{ "a": "b" }
// Patch
{ "a": { "$d": 0 } }
// Result
{}// Original
{
"a": "b",
"c": {
"d": "e",
"f": "g"
}
}
// Patch
{
"a": "z",
"c": {
"f": { "$d": 0 }
}
}
// Result
{
"a": "z",
"c": {
"d": "e",
}
}It defines a remote function that can be used later to make a remote procedure call.
{ "$f": <function_id> }Examples
// Original
{}
// Patch
{ "loginUser": { "$f": 975 } }
// Result in Javascript
{ "loginUser": function(){} }The replace type replaces objects at the target location with a new object.
{ "$r": <new_object> }Examples
// Original
{ "data": { "a": 1, "b": 2 } }
// Patch
{ "data": { "$r": { "c": 3 } } }
// Result
{ "data": { "c": 3 } }To do
Types are always defined as an Object with only one key and value. The key name must have the dollar character at the beginning.
Examples of valid types
{ "$clone": 0 }
{ "$clone": { "more":"data" } }
{ "$push": ["any", "JSON", "value"] }Examples of invalid types
{ "mytype": 0 }
{ "$clone": 0, "$more":"data" }