sagold/json-pointer

set method creates an object instead of an array

Closed this issue · 10 comments

Hello,
Thanks so much for the library :)
Apologies if I'm missing something here, but shouldn't pointer.set({ }, '/foo/0/bar', 1) create { foo: [ { bar:1 } ] } instead of { foo: { '0' : { bar: 1 } } }?

Hi Marcus,

"0" is ambiguous if there is no array or object to determine the type of data. In the Readme it says that

pointer.set({}, '/foo/[]/bar', 1);

creates the data you expect.
In the tests we can see that setting a specific index is done by

pointer.set({}, '/foo/[0]/bar', 1);

This should probably be mentioned in the Readme too.

Does this help?

A documentation to pointer.set using arrays has been added:
https://github.com/sagold/json-pointer?tab=readme-ov-file#array.

Thanks for following up so quickly, Sascha.

I actually have tried the solution you've mentioned previously but noticed this happens

const obj = {};
pointer.set(obj, '/list/[0]/itemA', 1)
// { list: [ { itemA: 1 } ] }
pointer.set(obj, '/list/[0]/itemB', 1)
// { list: [ { itemB: 1 } ] }

So as you can see, the /[0]/ directive completely replaces the current index instead of appending to it, as you'd expect and how it works with /list/0/itemA followed by /list/0/itemB

The only solution to the problem I could find so far was using the @sagold/json-query module, which works as expected without the need to adding brackets, although at the disadvantage of then not recognising the pointer.set(obj, '/list/[]', {}) directive to push to an array :)

I see. That looks like unexpected behaviour. I can change that until tomorrow.

Thank you for pointing this out.

btw, would you prefer the json-query support over json-pointer set?

Thanks so much, Sascha
Yes, I believe that /list/0 is more intuitive than /list/[0]. So json-query support would be best in my opinion. 😀

Thanks again

Hi Marcus,

a fix has been published with @sagold/json-pointer@6.0.2:

const obj = {};
pointer.set(obj, '/list/[0]/itemA', 1)
// { list: [ { itemA: 1 } ] }
pointer.set(obj, '/list/[0]/itemB', 1)
// { list: [ { itemA: 1, itemB: 1 } ] }

Please note that with version @sagold/json-pointer@7.0.0, numbers in paths are treated as array-indices.

pointer.set({}, '/foo/0/bar', 1)
// { foo: [ { bar: 1 } ] }

pointer.set({}, '/foo/[0]/bar', 1)
// { foo: [ { bar: 1 } ] }

while using object-syntax {0} will create an object

pointer.set({}, '/foo/{0}/bar', 1)
// { foo: { 0: { bar: 1 } } }

More details can be found in README.

Cheers,
Sascha

Thanks so much for working on this so quickly, Sasha. That's great as it's going to be super useful so I don't need to create objects with empty arrays anymore.
Also thanks for keeping up with semver and launch the number notation under a major.
Have a nice week ahead.

You are welcome!