spark85 / json-path

Automatically exported from code.google.com/p/json-path
0 stars 0 forks source link

More flexible "put" (amend-or-new) operation #62

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
Basically the new write API is a great step forward but a little cumbersome and 
I've been pressed into writing a wrapper around it which doesn't seem right.

JsonPath.parse(DOC).set("$.a",1); // This is fine - replaces existing values 
only

JsonPath.parse("{}").put("$","a",1); // This is equivalent but is difficult to 
work with
It only operates on the direct children of the basepath and insists on the 
client supplying the basebath seperately to a (potentially) new key. It feels 
like the underlying object-graph, though still hidden, is distorting the 
jsonpath interface.

I propose two levels of improvement (can split this enhancement request after 
discussion maybe)

A) Infer the parent

This single-argument put still only works on immediate children but does not 
require splitting. The path is compiled, evaluated up to the parent of the leaf 
node and all matches are then set (amend-or-new). 
  JsonPath.parse("{}").put("$.a",1) = {"a":1}
  JsonPath.parse("{"a":{}}").put("$..a.b",1) = {"a":{"b":1}}
  JsonPath.parse("[{},{}]").put("$[0].b",1) = [{"b":1},{}]
  JsonPath.parse("[{},{}]").put("$[0]",1) = [1,{}] // This one may be a little harder than others?

Need to think about the impact of puts made on the initial results (you might 
have completely removed a subtree that contained a further match). My thoughts 
were are to sort by absolute path length and convert the longest ones first but 
then i realise filters still "look ahead"... Hence, I think this would simply 
be a documented user-beware case.

B) Create deterministic parents

Using the compiled path, it should be possible to create the structure 
deterministically implied by the request. 
  JsonPath.parse("{}").put("$.a.b",1) = {"a":{"b":1}}
  JsonPath.parse("{}").put("$.a[1].b",1) = {"a":[null,{"b":1}]}

non-determinite path steps are selectors-only. 
  JsonPath.parse("{}").put("$.a[*].b",1) = {};
  JsonPath.parse("{"a":[null]}").put("$.a[*].b",1) = {"a":[{"b":1}]};
  JsonPath.parse("{"a":1,"b":{}}").put("$.a[*].b",1) = {"a":[{"b":1}]};

This should be a new verb but I can't think of one without changing the 
existing ones
set -> replace
put -> set
  (note it would be exactly equivalent in function so existing "set" users wouldn't notice)
put = put-with-create

What version of the product are you using? On what operating system?
1.2.0

Original issue reported on code.google.com by drekb...@gmail.com on 27 Nov 2014 at 2:04

GoogleCodeExporter commented 9 years ago

Original comment by kalle.st...@gmail.com on 10 Dec 2014 at 8:34