npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

td-patch

v0.2.1

Published

A JSON Patch module for Node.js and the browser.

Downloads

22

Readme

td-patch

A JSON Patch module for Node.js, the browser, and the command line.

Install it with

npm install td-patch -g

or download the minimized version to be used in a browser.


For XML there are XSLT and XQuery for manipulating documents, and XPath for pointing to nodes in a document. What is the corresponding solution for JSON? It is JSON Path and JSON Pointer. Both XML and JSON are data interchange formats, but they are quite different. XML is more complex with attributes, namespaces, comments, and schemas. It needs complex tools. JSON is very close to the native data structure of many programming languages, JavaScript in particular. The natural way is to handle data manipulation in a programming language of choice, but there are situations where there is a need to write down a transformation in a standardized way, so it can be applied to a JSON later on. This is mostly what XSLT and XQuery is about, making templates for transformation of documents. JSON Patch is exactly that for JSON.

JSON Pointer

The first thing we need is to have a way to point at a node in a JSON structure, an address string. JSON Pointer is the simplest possible solution to that.

var json = {
	"module": "td-path",
	"version": "0.1.0",
	"keywords": [
    	"tripledollar",
    	"json-path",
    	"json-pointer"
  	],
  	"bin": {
  		"tdpath": "bin/tdpath.js"
  	},
  	"author": "steenk",
  	"license": "MIT"
},

	pointer1 = "/",
	pointer2 = "/keywords/1",
	pointer3 = "/version",
	pointer4 = "/bin/tdpath"

A JSON structure consists of a tree of arrays and objects with key/value pairs. To access a key/value pair the key is used, and to access any item in an array an index number is used. JSON Pointer use a combination of these keys and index numbers with slashes dividing them. It looks like an Internet address, which is also the meaning.

So what if a key has a "/" inside it? To prevent the key from being split into two invalid keys, it has to be escaped. The escape character used in JSON Pointer is "~". So the "/" in the key name is replaced by "~1" in the JSON Pointer string. That leaves the question of what if the key has a "~" in it? Well then it has to be replaced by "~0". These cases are not so common and all other valid characters in a JSON key goes without change.

JSON Patch

While JSON Pointer gives us a way to point to the inner data structures of a JSON document, JSON Patch gives us a way to describe transformations of a JSON document. JSON Patch is itself a JSON document. It always consists of an array with one or many patches. Each patch will do one of six operations on the JSON document, test, remove, add, replace, move, and copy. The patches will be applied in sequence, so it is actually an activity list for a transformation. The transformation is atomic, meaning that if any of the operation steps fails, the whole transformation fails. Five of the six operations will try to transform the JSON in some way, but the test operation just do a validation, which if it fails stops the whole transformation. Here is an example. It starts with the object {"b": "bar", "c": [1, 2, 3, 4], "d": {"e": {"f": {} } } } and transform it with a sequence of patches.

var res = tdpatch(
	{"b": "bar", "c": [1, 2, 3, 4], "d": {"e": {"f": {} } } }, 
	[
	  {"op": "add", "path": "/a", "value": "foo"},
	  {"op": "test",  "path": "/a",  "value": "foo"},
	  {"op": "remove",  "path": "/b"},
	  {"op": "remove",  "path": "/c/2"},
	  {"op": "replace",  "path": "/a",  "value": "bar"},
	  {"op": "replace",  "path": "/d/e/f",  "value": "foobar"}
	]
);

// res: { "c": [ 1, 2, 4 ], d: { e: { f: 'foobar' } }, a: 'bar' }

All patches has the properties "op" and "path", add, test, and replace have the "value" property also, and move and copy have the "from" property also. In res comes the transformed object { c: [ 1, 2, 4 ], d: { e: { f: 'foobar' } }, a: 'bar' } if it succeeds, otherwise res will be undefined.

Chain Transformation

An alternative is to build up the transformation with chaining. If only the the first parameter is put into tdpatch, the patches can be applied with methods chained together and finally run by the run method. In the parameter list of these methods, the first one is always the path.

var obj = {"b": "bar", "c": [1, 2, 3, 4], "d": {"e": {"f": {} } } };

// start at transformation
var trans = tdpatch(obj)
	.add("/a", "doggy");

// add a test
trans.test("/a",  "doggy");

// chain the rest and run
var res = trans.remove("/b")
	.remove("/c/2")
	.replace("/a",  "billi")
	.replace("/d/e/f",  "foobar")
	.run();

console.log(res);

With this method you can build up a long patchlist, and whenever you want to export your patches do it with JSON.stringify(trans.patches), and you get a JSON string you can save for later use.

How to Get the Library

In Node.js this is what to do:

var tdpatch = require('td-patch');

var res = tdpatch({}, [{op: 'add', path: '/foo', value: 'bar'}]);
// res: {foo: 'bar'}

In the browser the prefered way is to use an AMD module loader, like Require.js, but without a module loader it will register a global method window.tdpatch.

require(['td-patch'], function (tdpatch) {
	
	var tdpatch = require('td-patch');
	var res = tdpatch({}, [{op: 'add', path: '/foo', value: 'bar'}]);
	// res: {foo: 'bar'}
});

The Command Tool

Installed in Node.js with the "-g" flag gives a command tool called "tdpatch".

tdpatch --help
Usage: tdpatch <json file> <json patch file> [<output file>]

The JSON Patch file has an array with one or more patches in it. It has to be in valid JSON format. The output file is optional.