tidwall / gjson

Get JSON values quickly - JSON parser for Go
MIT License
13.88k stars 841 forks source link

the return result has key absent problem #321

Open Storm-Born opened 1 year ago

Storm-Born commented 1 year ago

{ "persons": [ { "name":"wangyiyi", "age": 20, "address":"china" }, { "name":"lisi", "age": 33, "address":"england" }, { "name":"luosan", "age": 40, "address":"iceland" } ] } json data is above. I used the jsonpath "persons.#.[name,age,sex,address]", as you see, a give a key not exists. then gjson eat this key and just give me a result like blew:

[["wangyiyi",20,"china"],["lisi",33,"england"],["luosan",40,"iceland"]]

this behavior cause a problem that I don't know which key has no value and I can't map the existed value to it's key rightly.

volans- commented 1 year ago

@Storm-Born as mentioned recently in https://github.com/tidwall/gjson/issues/295#issuecomment-1483809118 you can get a default value in arrays with the [key,!"default"].0 pattern. So in this case you could do (using null as default value, adapt it based on your needs):

persons.#.[[name,!null],[age,!null],[sex,!null],[address,!null]].#.0

to get:

[["wangyiyi",20,null,"china"],["lisi",33,null,"england"],["luosan",40,null,"iceland"]]

That said I think that relying on position in arrays for data it's usually brittle, hash keys are safer to be sure you're getting the right data.

Storm-Born commented 1 year ago

@Storm-Born as mentioned recently in #295 (comment) you can get a default value in arrays with the [key,!"default"].0 pattern. So in this case you could do (using null as default value, adapt it based on your needs):

persons.#.[[name,!null],[age,!null],[sex,!null],[address,!null]].#.0

to get:

[["wangyiyi",20,null,"china"],["lisi",33,null,"england"],["luosan",40,null,"iceland"]]

That said I think that relying on position in arrays for data it's usually brittle, hash keys are safer to be sure you're getting the right data.

thank you.it works right. and I agree with your opinion but I don't see the hash keys syntax in the guidline, how should I write the path express to get the result format like below.

[{"name":"wangyiyi","age":20, "sex":null, "address":"china"},{"name":"lisi","age":33,"sex":null,"address":"england"},{"name":"luosan","age":40,"sex":null,"address":"iceland"}]
volans- commented 1 year ago

@Storm-Born I would just query for persons and then check on the code that parses the results if an attribute is missing, but of course that depends what is consuming the data.

If you really want to get that output you can use:

persons.#.[{"sex":!null},@this].@join

Explanation: for each person object create a multipaths array with an object with the literal null value for sex, and the current person object, then joining them so that the person object would override any value set on the left if there are duplicate keys.

That gives you:

[{"sex":null,"name":"wangyiyi","age":20,"address":"china"},{"sex":null,"name":"lisi","age":33,"address":"england"},{"sex":null,"name":"luosan","age":40,"address":"iceland"}]

but if any of the items has a vaue for the sex property it will get that.

Maybe tidwall knows a better way to achieve this though.