Repository navigation
wrap option returns the same result for arrays whether true or false #86
Description
Activity
This would be the more intuitive behavior.
However,
wraphas worked as follows...- When no results are found:
- If
wrapistrue(the current default), return an empty array. - If
wrapisfalse, returnundefined.
- If
- When a single non-array result is found:
- If
wrapistrue(the current default), follow case 3 . - If
wrapisfalse, return the item as is.
- If
- When more than one result or an array is found, return the results within an array (regardless of
wrap).
Thus if you get array results with
wrap: false, you know you either grabbed an array or got multiple results and can just use the results as is, without any unwrapping. You know withundefinedthat nothing was found, and if you got a scalar, that that was the single value.A better naming for this alternative
wrap: false(and I think preferable) behavior might beunwrap: true.Perhaps we could add an option that avoids breaking existing code and follows the behavior you describe (of unwrapping arrays as well):
wrap: 'never'.And perhaps we should also add an option of
wrap: 'found'with this behavior:- When no results are found, return
undefined. - For any other case, return the results wrapped within an array
This approach would have the benefit over
wrap: falseof allowing a single approach with non-array or array results and single or multiple results. It would also have the benefit overwrap: false(andwrap: true) of being able to distinguish between finding the resultundefinedand not finding any result.(Note the responsible code to change is at https://github.com/s3u/JSONPath/blob/master/src/jsonpath.js#L202-L214 , esp. 203-205)
- When no results are found:
Just my thoughts/observations...
Point 3 above about how
wraphas worked doesn't match what I am seeing; I see an array where the first item is also an array (the one result)...ending up with a multidimensional array is odd and don't think unwrapping the result array is anyway required, if you're using an expression with the expectation of getting an array then you do whatever you need to with the returned result in your own code doesn't seem like the responsibility of this library.Ideally
wrap: falseshould be consistent in that it returns the result (if single match); if you are going to change the data type ofwrapanyway then it is already a breaking change so why not avoid the confusion of what the different wrap values mean and just keep it asbooleanwith predictable behaviour.Thanks for your comments. I'll give this some more thought if I'm revisiting this, but tbh, this library is a low priority for me atm.
Reacted by Tobias HochgürtelA more accurate summary of current behavior for
wrap: falsethan my earlier statement is as follows:- No matches: return undefined
- One match that did not come through an array-expression operator (for example filter, wildcard, slice, union, or recursive descent): return the value directly.
- Otherwise: return an array
I propose a new option—one which preserves backward compatibility:
collapseSingleMatch. This will throw if it is not used withwrap: false.When enabled, it will make single-match behavior consistent by returning the value directly for any single match, regardless of path shape.
Sound good?
Reacted by Rich Turner
Given the following JSON:
{ "store": { "book": [ { "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95 }, { "category": "fiction", "author": "Evelyn Waugh", "title": "Sword of Honour", "price": 12.99 } ] } }JSONPath returns the same result for the following 2 queries:
JSONPath({data: data, path: "$.store.book", wrap: true});JSONPath({data: data, path: "$.store.book", wrap: false});I believe for wrap: false, the outer array should be removed like this: