bolerio / mjson

Lean JSON Library for Java, with a compact, elegant API.
Apache License 2.0
82 stars 26 forks source link

Find a json objects key in the parent json #7

Closed rob42 closed 8 years ago

rob42 commented 9 years ago

I have several cases where I have the json element in a hierarchy (eg after an event has occurred) but I need to know its key in the parent json. Basically I need to recurse the path back to the top level. This is remarkably hard to do efficiently! Ive considered several possibilities: 1) Use google guava BiMap instead of HashMap in the ObjectJson. Then use .inverse() to find the key. Would work but BiMap must have unique values (a Set), and I suspect that will cause trouble 2) store the key in the child object when the child is created. Also works but needs care or it causes bugs when serialising or when making misc changes like moving parent. 3) store a ref to the parent key in the child somehow - much like 2) 4) iterate the keys in the parent looking for an equals() match on the associated value - nice, but is it efficient in a big parent? What about two separate keys with the same value? - the BiMap problem.

Any ideas?

rob42 commented 9 years ago

Just noticed in the JsonObject.set(String property, Json el) method you have:

el.enclosing = this;

Maybe an el.key attribute would work here. The a getParentKey() method?

bolerio commented 9 years ago

Yes, I maintained a link back to the parent in order to make the 'up()' method word. However, that is a bit shaky because it assumes there is only one parent, which is not necessarily the case unless you make sure to clone every time an element would acquire multiple parents. Not sure if BiMap's problem is similar. I think you could try (4) and if performance becomes a problem, switch to (2). If you have to deal with multiple parents and multiple values, then you'd need a "parentMap" in each value, an IdentityHashMap<Json, Object> where you map each parent to the key within that parent. That will work if the parent is an object or an array.

rob42 commented 9 years ago

I just implemented el.parentKey, and its working nicely. But I dont have objects with multiple parents. Is that a normal case?

rob42 commented 9 years ago

Ive added a pull request with my getParentKey solution. Maybe just fill in the parentKey when its easy (eg one objectjson parent) and return null or unsupportedException in complex cases like arrays or multi-parents?

bolerio commented 9 years ago

Hi rob42,

I think not having multiple parents is the more common case. But you do want that ability because larger data structures do tend to be graphs rather than trees. For example in the OpeCiRM project where mJson is heavily used for everything, things do have multiple parents. Though we never need to go up the parent chain and that's why thing haven't blown up so far :)

To fully solve the problem, we do need the ability to deal with multiple parents and we also need to make your solution somehow optional so that the extra overhead is not incurred by people that don't need it. I think it's an unusual requirement to need to know the parent key. I've had situations where I need the parent key of course, but it's always at a spot where I'm processing top-down the JSON structure so I already have it, and it's matter of passing it as an extra parameter. Or maintaining a "path" extra argument to recursive methods that traverse the JSON.

rob42 commented 9 years ago

Borislav, In my case I have only the json element, as an attribute to an update event. So I need to find the full path by recursing upwards.

My case would break for multiple parents anyway, as recursing up the tree assumes only one path - eg how do you recurse up two paths? You get two full paths at least and it gets worse with more multiples higher in the tree.

As far as extra overhead, the single parent case is very minimal - same as the up() attribute. I just set the key name too. I will see where my mod leads as my use case gets more complex and come back with a multiple parent solution