Data formats

JSON Patch

JSON Patch (RFC 6902) and Merge Patch (RFC 7396): the difference between two values as operations, and patches applied.

Version 1.0.0 · 3 functions · 1 crate

#json#api#diff#history

Functions

What use json_patch.qwer gives a program, with the types Quillo sees. To take only some, or under other names: use json_diff, json_patch_apply from json_patch (Quillo 0.6).

json_diff(before: any, after: any) → anyor an error

The RFC 6902 patch that turns before into after: a list of { op, path, value } (add, remove, replace), empty when they are equal.

json_patch_apply(value: any, patch: any) → anyor an error

value with an RFC 6902 patch applied (add, remove, replace, move, copy and test). All or nothing: when one operation fails (a path that is not there, a test that does not hold), the error names it and nothing is applied.

json_merge(value: any, merge_patch: any) → any

value with an RFC 7396 merge patch applied: the patch's keys replace the value's, null removes a key, maps merge all the way down, lists are replaced whole. What most PATCH endpoints take.

Get it

$ quillo install json_patch               # json_patch.qwer into this folder$ quillo install json_patch --example     # and its example, json_patch.qwe

Or with curl:

$ curl -O https://quillolang.org/plugins/files/json_patch.qwer$ curl -O https://quillolang.org/plugins/files/json_patch.qwe

Then, in your program, all of it or only what you call:

main.qwe
use json_patch.qweruse json_diff, json_patch_apply from json_patch      // Quillo 0.6: only these

It uses this crate, which cargo fetches the first time the plugin is built:

[dependencies]
json-patch = "3"

Example

json_patch.qwe
// A PATCH endpoint that takes merge patches, an undo built from the diff, and a change history.////   quillo run json_patch.qwe      then open http://localhost:8080/historyuse "json_patch.qwer"let product = { sku: "B7", name: "Blue mug", price: 12.5, tags: ["kitchen", "blue"], stock: { amsterdam: 4, london: 0 } }route PATCH /products/b7 = json_merge(product, request.json)route GET /history {    let after = json_merge(product, { price: 11.0, tags: ["kitchen", "blue", "sale"], stock: { london: 12 }, name: null })    let change = json_diff(product, after)?    let undo = json_diff(after, product)?    { after, change, undone: json_patch_apply(after, undo)? == product }}route GET /apply {    let patch = [{ op: "test", path: "/price", value: 12.5 }, { op: "replace", path: "/price", value: 9.99 }, { op: "add", path: "/tags/-", value: "gift" }]    { patched: json_patch_apply(product, patch)?, stale: json_patch_apply(json_merge(product, { price: 13 }), patch).error }}
$ quillo run json_patch.qwe$ curl 'localhost:8080/history'$ curl 'localhost:8080/apply'

Source

json_patch.qwer
//! JSON Patch (RFC 6902) and JSON Merge Patch (RFC 7396): the difference between two values as a list of operations, and patches applied, for PATCH endpoints, undo and audit trails.//! version: 1.0.0//!//! [dependencies]//! json-patch = "3"use serde_json::Value;/// The RFC 6902 patch that turns `before` into `after`: a list of `{ op, path, value }` (`add`, `remove`, `replace`), empty when they are equal.pub fn json_diff(before: serde_json::Value, after: serde_json::Value) -> Result<Value, String> {    serde_json::to_value(json_patch::diff(&before, &after)).map_err(|e| e.to_string())}/// `value` with an RFC 6902 `patch` applied (`add`, `remove`, `replace`, `move`, `copy` and `test`). All or nothing: when one/// operation fails (a path that is not there, a `test` that does not hold), the error names it and nothing is applied.pub fn json_patch_apply(value: serde_json::Value, patch: serde_json::Value) -> Result<Value, String> {    let p: json_patch::Patch = serde_json::from_value(patch).map_err(|e| format!("not a JSON Patch (a list of {{ op, path, ... }}): {}", e))?;    if p.0.len() > 10_000 {        return Err("at most 10,000 operations".into());    }    let mut v = value;    json_patch::patch(&mut v, &p).map_err(|e| e.to_string())?;    Ok(v)}/// `value` with an RFC 7396 merge patch applied: the patch's keys replace the value's, `null` removes a key, maps merge all/// the way down, lists are replaced whole. What most PATCH endpoints take.pub fn json_merge(value: serde_json::Value, merge_patch: serde_json::Value) -> Value {    let mut v = value;    json_patch::merge(&mut v, &merge_patch);    v}
Thread
106Useful? Like it, or add to its thread below.

Thread 0 posts

On JSON Patch: questions, tips, corrections, and code that uses it.

No posts yet. The first one opens the thread.