From cde13e5f3b9663edf118169a3e5f03bd0a778b04 Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Wed, 23 Oct 2013 18:15:56 -0700 Subject: [PATCH] ugly fix for get single/get array --- lib/jsonpath.js | 53 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/lib/jsonpath.js b/lib/jsonpath.js index 41bb487..0f6e4ad 100644 --- a/lib/jsonpath.js +++ b/lib/jsonpath.js @@ -71,17 +71,24 @@ function jsonPath(obj, expr, arg) { }, trace: function(expr, val, path) { // no expr to follow? return path and value as the result of this trace branch - if (!expr || !expr.length) return [{path: path, value: val}]; + if (!expr.length) return path.length ? {path: path, value: val} : undefined; var loc = expr[0], x = expr.slice(1); // the parent sel computation is handled in the frame above using the // ancestor object of val - if (loc === '^') return [{path: push(path, loc), expr: x, parentSelection: true}]; + if (loc === '^') return path.length ? {path: push(path, loc), expr: x, parentSelection: true} : undefined; // we need to gather the return value of recursive trace calls in order to - // do the parent sel computation - var ret = []; - function addRet(elems) { ret = ret.concat(elems); } + // do the parent sel computation. The "not wrap" special case makes + // the whole result computation much more complicated. + var ret = P.wrap ? [] : undefined; + function addRet(elems) { + if (!ret) { ret = elems; return; } + if (!elems) return; + if (!Array.isArray(elems)) elems = [elems]; + if (!Array.isArray(ret)) ret = [ret]; + ret = ret.concat(elems); + } if (val && val.hasOwnProperty(loc)) // simple case, directly follow property addRet(P.trace(x, val[loc], push(path, loc))); @@ -116,9 +123,16 @@ function jsonPath(obj, expr, arg) { // we check the resulting values for parent selections. for parent // selections we discard the value object and continue the trace with the // current val object + if (!ret) return ret; + if (!Array.isArray(ret)) { + return ret.parentSelection ? P.trace(ret.expr, val, ret.path) : ret; + } return ret.reduce(function(all, ea) { - if (!ea.parentSelection) { all.push(ea); return all; } - return all.concat(P.trace(ea.expr, val, ea.path)); + ea = ea.parentSelection ? P.trace(ea.expr, val, ea.path) : ea; + if (!ea) return all; + if (!Array.isArray(ea)) all.push(ea); + else all = all.concat(ea); + return all; }, []); }, walk: function(loc, expr, val, path, f) { @@ -161,15 +175,22 @@ function jsonPath(obj, expr, arg) { if (expr && obj && (resultType == "value" || resultType == "path")) { var exprList = P.normalize(expr); if (exprList[0] === "$" && exprList.length > 1) exprList.shift(); - var result = P.trace(exprList, obj, ["$"]).reduce(function(result, ea) { - var valOrPath = ea[resultType]; - if (P.flatten && valOrPath instanceof Array) { - result = result.concat(valOrPath); - } else { - result.push(valOrPath); - } - return result; - }, []); + var result = P.trace(exprList, obj, ["$"]); + if (!result) return P.wrap ? [] : false; + if (!Array.isArray(result)) { + result = result[resultType]; + if (P.wrap) result = [result]; + } else { + result = result.reduce(function(result, ea) { + var valOrPath = ea[resultType]; + if (P.flatten && valOrPath instanceof Array) { + result = result.concat(valOrPath); + } else { + result.push(valOrPath); + } + return result; + }, []); + } return result; } }