tidwall / gjson

Get JSON values quickly - JSON parser for Go
MIT License
14.2k stars 846 forks source link

Tilde operator treats values other than true and 1 as false #327

Closed kcaashish closed 1 year ago

kcaashish commented 1 year ago

I tested vals.#(b==~false)#.a with the example provided:

{
  "vals": [
    { "a": 1, "b": "true" },
    { "a": 2, "b": true },
    { "a": 3, "b": false },
    { "a": 4, "b": "0" },
    { "a": 5, "b": 0 },
    { "a": 6, "b": "1" },
    { "a": 7, "b": 1 },
    { "a": 8, "b": "true" },
    { "a": 9, "b": false },
    { "a": 10, "b": null },
    { "a": 11 }
  ],
  "anything": "else"
}

And it gives the desired result: [3,4,5,9,10,11]

However, when we have values other than true or 1, they are treated as false:

{
  "vals": [
    { "a": 1, "b": "something" },
    { "a": 2, "b": "else" },
    { "a": 3, "b": false },
    { "a": 4, "b": "0" },
    { "a": 5, "b": 0 },
    { "a": 6, "b": "1" },
    { "a": 7, "b": 1 },
    { "a": 8, "b": "true" },
    { "a": 9, "b": false },
    { "a": 10, "b": null },
    { "a": 11 }
  ],
  "anything": "else"
}

Gives: [1,2,3,4,5,9,10,11]

Try: https://go.dev/play/p/ey6dS3zFk3p

I don't this is the desired behavior. Is there a way to get the fields, for which the data is either null or missing?

tidwall commented 1 year ago

In your case, gjson is simply treating ~false as all values that are not true-ish.

I agree that this is probably not desired.

Rather, we likely want to more explicit, where all true-ish values are true, and all false-ish are false.

I made some updates moments ago to the syntax that addresses the ~false issue.

Now vals.#(b==~false)#.a returns [3,4,5,9,10,11].

I also added two more tilde types:

~null      Converts null and non-existent values to true
~*         Converts any existing value to true

Is there a way to get the fields, for which the data is either null or missing?

Yes, using ~null or ~*:

vals.#(b==~null)#.a   => [10,11]
vals.#(b!=~null)#.a   => [1,2,3,4,5,6,7,8,9]
vals.#(b==~*)#.a      => [1,2,3,4,5,6,7,8,9,10]
vals.#(b!=~*)#.a      => [11]
kcaashish commented 1 year ago

Great! Just tried and it works like a charm! ~* is a handy addition too. Thank you!

tidwall commented 1 year ago

No problem. I'm happy to hear it's working. :)