From 6232e8ddb83538c141e05fbd5965770662659496 Mon Sep 17 00:00:00 2001 From: Marc Bachmann Date: Wed, 27 May 2015 02:04:45 +0200 Subject: [PATCH] Support /- and nested properties --- jsonpointer.js | 62 ++++++++++++++++++++++++++++++++++---------------- test.js | 18 +++++++++++---- 2 files changed, 57 insertions(+), 23 deletions(-) diff --git a/jsonpointer.js b/jsonpointer.js index 006f85e..8fb3397 100644 --- a/jsonpointer.js +++ b/jsonpointer.js @@ -11,34 +11,51 @@ var untilde = function(str) { } var traverse = function(obj, pointer, value) { - // assert(isArray(pointer)) var part = untilde(pointer.shift()); - if(!obj.hasOwnProperty(part)) { - return null; + var isJustReading = arguments.length === 2; + + if (obj[part] == null) { + if (isJustReading) return null; + + // support setting of /- + if (part === '-' && obj instanceof Array) { + part = obj.length; + } + + // support nested objects/array when setting values + var nextPart = pointer[0]; + if (nextPart === '-' || !isNaN(nextPart)) { + obj[part] = []; + } else if (nextPart) { + obj[part] = {}; + } } - if(pointer.length !== 0) { // keep traversin! - return traverse(obj[part], pointer, value); + + // keep traversing + if (pointer.length !== 0) { + if (isJustReading) { + return traverse(obj[part], pointer); + } else { + return traverse(obj[part], pointer, value); + } } + // we're done - if(typeof value === "undefined") { - // just reading + if (isJustReading) { return obj[part]; } + // set new value, return old value - var old_value = obj[part]; - if(value === null) { + var oldValue = obj[part]; + if (value === null) { delete obj[part]; } else { obj[part] = value; } - return old_value; + return oldValue; } -var validate_input = function(obj, pointer) { - if(typeof obj !== "object") { - throw new Error("Invalid input object."); - } - +var compilePointer = function(pointer) { if(pointer === "") { return []; } @@ -47,15 +64,22 @@ var validate_input = function(obj, pointer) { throw new Error("Invalid JSON pointer."); } - pointer = pointer.split("/"); - var first = pointer.shift(); - if (first !== "") { - throw new Error("Invalid JSON pointer."); + if (!(pointer instanceof Array)) { + pointer = pointer.split("/"); + if (pointer.shift() !== "") throw new Error("Invalid JSON pointer.") } return pointer; } +var validate_input = function(obj, pointer) { + if(typeof obj !== "object") { + throw new Error("Invalid input object."); + } + + return compilePointer(pointer); +} + var get = function(obj, pointer) { pointer = validate_input(obj, pointer); if (pointer.length === 0) { diff --git a/test.js b/test.js index 1c67d7f..a596843 100644 --- a/test.js +++ b/test.js @@ -1,5 +1,5 @@ -var assert = require("assert"); -var jsonpointer = require("./jsonpointer"); +var assert = require('assert'); +var jsonpointer = require('./jsonpointer'); var obj = { a: 1, @@ -24,6 +24,16 @@ assert.equal(jsonpointer.set(obj, "/d/e/0/a", 4), 3); assert.equal(jsonpointer.set(obj, "/d/e/1/b", 5), 4); assert.equal(jsonpointer.set(obj, "/d/e/2/c", 6), 5); +// set nested properties +assert.equal(jsonpointer.set(obj, "/f/g/h/i", 6), undefined); +assert.equal(jsonpointer.get(obj, "/f/g/h/i"), 6); + +// set an array +assert.equal(jsonpointer.set(obj, "/f/g/h/foo/-", 'test'), undefined); +arr = jsonpointer.get(obj, "/f/g/h/foo") +assert(Array.isArray(arr), 'set /- creates an array.'); +assert.equal(arr[0], 'test'); + assert.equal(jsonpointer.get(obj, "/a"), 2); assert.equal(jsonpointer.get(obj, "/b/c"), 3); assert.equal(jsonpointer.get(obj, "/d/e/0/a"), 4); @@ -62,8 +72,8 @@ assert.equal(jsonpointer.get(complexKeys, "/~1"), null); var ary = [ "zero", "one", "two" ]; assert.equal(jsonpointer.get(ary, "/01"), null); -//assert.equal(jsonpointer.set(ary, "/-", "three"), null); -//assert.equal(ary[3], "three"); +assert.equal(jsonpointer.set(ary, "/-", "three"), null); +assert.equal(ary[3], "three"); // Examples from the draft: var example = {