tidwall / gjson

Get JSON values quickly - JSON parser for Go
MIT License
14.21k stars 847 forks source link

can't get length of array if the path has a number as key ":4". #312

Open Databingo opened 1 year ago

Databingo commented 1 year ago

suppose json is : j := [0,1,2,3,{"4": {"test0":[1,2,3,"4"]}}] run: length := gjson.Get(j, "4.:4.test0.#").Int() get 0;

but if change data key from number "4" to string "a": j := [0,1,2,3,{"a": {"test0":[1,2,3,"4"]}}] then run: length := gjson.Get(j, "4.a.test0.#").Int() get 4.

The different is the path where change :4 to a. Is this a problem or I miss something?

Databingo commented 1 year ago

and seems like can't insert number item in empty array: sjson.Set("[]", 0, 0 ) return []

volans- commented 1 year ago

suppose json is : j := [0,1,2,3,{"4": {"test0":[1,2,3,"4"]}] run: length := gjson.Get(j, "4.:4.test0.#").Int() get 0;

The key in your JSON is just 4, not :4. For the provided JSON the query should be 4.4.test0.#. If instead your JSON is modified to have a :4 key then your current query ( 4.:4.test0.# ) works fine.

Databingo commented 1 year ago

suppose json is : j := [0,1,2,3,{"4": {"test0":[1,2,3,"4"]}}] run: length := gjson.Get(j, "4.:4.test0.#").Int() get 0;

The key in your JSON is just 4, not :4. For the provided JSON the query should be 4.4.test0.#. If instead your JSON is modified to have a :4 key then your current query ( 4.:4.test0.# ) works fine.

Thank you but I think query .4 is for the 5th position of an array, so for a string "4" as key we need use ":4" to indicate it. Here is the document https://github.com/tidwall/sjson#path-syntax say:

"Normally number keys are used to modify arrays, but it's possible to force a numeric object key by using the colon character:" { "users":{ "2313":{"name":"Sara"}, "7839":{"name":"Andy"} } } A colon path would look like: "users.:2313.name" >> "Sara"

Finally I find out :4 is for sjson pacakge that modify json, not gson packege that query json, thanks a lot! I chang to 4.4.test0.# then get the corrent length.

volans- commented 1 year ago

@Databingo but that's sjson documentation though and I don't see the same note on the gjson documentation. You can test what I've mentioned earlier in https://gjson.dev/

The first .4 returns the 5th element that is an object ( {"4": {"test0":[1,2,3,"4"]}}) and at that point an additional .4 selects the key with value 4. And there is no possible ambiguity because as per JSON specifications object keys can only be strings.

Databingo commented 1 year ago

@volans- Thanks a lot, I got it, why not author keep gjson same syntax ":4" with sjson in case someone use number as object key accidentally?

Maybe package could figure out that's an object so .4 only be a key rather than an index of array, but ".:4" is much easier for user to explicitly express his intention of a numeric key.

Finally I think no need because user no need to consider which situation(array index or object key) it is when use a number in query.

Still have another question: seems like sjson can't insert number item in an empty array: sjson.Set("[]", 0, 0 ) return []

volans- commented 1 year ago

Sorry I'm not familiar with the sjson side of things, I'll leave that to @tidwall or others to answer.

Databingo commented 1 year ago

@volans- Thank you!

tidwall commented 1 year ago

@Databingo For sjson.Set("[]", 0, 0 ), the second param must be a string. https://go.dev/play/p/j3Zv32Op236

Databingo commented 1 year ago

@tidwall Thanks a lot, I got it!