joshbuddy/jsonpath

Delete elements from array using filter instead of index

viguza opened this issue · 6 comments

Hi @Skarlso, I don't think this is an issue but maybe a feature request actually. I have been working a lot with this project, and at some point, I found myself trying to delete elements from an array that matches a condition.

Something like this:

Input JSON

{ 'store' => {
      'book' => [
        { 'category' => 'reference',
          'author' => 'Nigel Rees',
          'title' => 'Sayings of the Century',
          'price' => 9,
          'tags' => %w[asdf asdf2] },
        { 'category' => 'fiction',
          'author' => 'Evelyn Waugh',
          'title' => 'Sword of Honour',
          'price' => 13 }
      ]
} }

JSONPath

JsonPath.for(@object).delete!("$.store.book[?(@.category == 'reference')]")

Expected output:

{ 'store' => {
      'book' => [
        { 'category' => 'fiction',
          'author' => 'Evelyn Waugh',
          'title' => 'Sword of Honour',
          'price' => 13 }
      ]
} }

However, it's returning the original object unmodified. The weird thing is that it works for search or even for replace.

JsonPath.for(@object).gsub!("$.store.book[?(@.category == 'reference')]") { |_| {} }

Output:

{ 'store' => {
      'book' => [
        {},
        { 'category' => 'fiction',
          'author' => 'Evelyn Waugh',
          'title' => 'Sword of Honour',
          'price' => 13 }
      ]
} }

Is this expected to work, or there's no logic to handle that? I searched on the tests file, but couldn't find a test case for this kind of deletion.

Hmm. I'll look into it. I think it should work if it works for the rest of the features. Makes sense for it to work there as well. 🤔

So I think I can hack this together although it won't be trivial. But I know where the thing lies :)

That would be great! I've been trying some debugging and following the code, but it's definitely a hard one. Still, good to know it can be done :)

Hey @viguza. Sorry this took so long. I was out for a long time sick. But now I'm better. I have a solution up. It's not a 100% great, but because we are dealing with recursive nodes, I can't just delete them while it's enumerating. So I had to rely on a mark/replace strategy here.

But hey, if it works... :)

Hey, @Skarlso the solution looks good to me. Thanks for the quick answer, I can't wait to try this on my code.

merging :)