Open DMLfor opened 1 year ago
@tidwall ^^
@ngarg-kr I played a bit with multipaths, literals and modifiers and I think I got basically the same behaviour you were looking for.
friends.#.others.#.[{"k":!null},{k}].@join.@values|#.@flatten
[["v","v"],[null,"v"],["v",null]]
The [{"k":!null},{k}]
part creates a multipaths array with the first item being {"k":null}
and the second item being the item with key "k"
coming from the others
array. That is repeated for each item in the others
array and if there is no key "k"
an empty object {}
is returned instead.
So the first part of the query friends.#.others.#.[{"k":!null},{k}]
returns:
[[[{"k":null},{"k":"v"}],[{"k":null},{"k":"v"}]],[[{"k":null},{}],[{"k":null},{"k":"v"}]],[[{"k":null},{"k":"v"}],[{"k":null},{}]]]
Then I apply the @join
modifier to merge the objects where the last wins, so where there is an empty object we keep the default literal value while where there is a value that one wins. See the dot-vs-pipe section of the docs for more details on the |
separator.
At that point we get only the values discarding the keys with the @values
modifier and finally apply the @flatten
modifier to get rid of the additional nested layer of arrays.
I'm not totally sure all the steps are working as expected, I got there with some trial and error, and some modifier got applied to the inner layer a little bit automagically, hence I'm not sure that's the intended behaviour or possibly some bug that could potentially change behaviour in the future.
Other possible alternatives that are simpler and would just need some additional parsing on your code are:
friends.#.others.#.[k]
result:
[[["v"],["v"]],[[],["v"]],[["v"],[]]]
2) query: friends.#.others.#.{k}
result:
[[{"k":"v"},{"k":"v"}],[{},{"k":"v"}],[{"k":"v"},{}]]
I also noticed that also using the @values
modifier gives the same result of (1) but I'm not sure why or if that's expected: friends.#.others.#.k.@values
@tidwall @volans- The Same problem, eg:
arr := gjson.GetBytes(jsonByte, `#(query%"*abc*")#.[resp.vid,resp.uid,resp.text,resp.errorno]`).Array()
Sometimes the key vid\uid may not exist, the length(arr[i]) is not 4 The expected result is a fixed array length of 4, and non-existent keys return null or empty
@tidwall @volans- The Same problem, eg:
arr := gjson.GetBytes(jsonByte, `#(query%"*abc*")#.[resp.vid,resp.uid,resp.text,resp.errorno]`).Array()
Sometimes the key vid\uid may not exist, the length(arr[i]) is not 4 The expected result is a fixed array length of 4, and non-existent keys return null or empty
If there is no way to return the default value, I can only append a string to complete the array length
@tidwall @volans- The Same problem, eg:
arr := gjson.GetBytes(jsonByte, `#(query%"*abc*")#.[resp.vid,resp.uid,resp.text,resp.errorno]`).Array()
Sometimes the key vid\uid may not exist, the length(arr[i]) is not 4 The expected result is a fixed array length of 4, and non-existent keys return null or empty
@litao09h could you provide the JSON input for your query please?
@tidwall @volans- The Same problem, eg:
arr := gjson.GetBytes(jsonByte, `#(query%"*abc*")#.[resp.vid,resp.uid,resp.text,resp.errorno]`).Array()
Sometimes the key vid\uid may not exist, the length(arr[i]) is not 4 The expected result is a fixed array length of 4, and non-existent keys return null or empty
@litao09h could you provide the JSON input for your query please?
We converted the log to json
a=11&b=12&c=13&d=14
a=21&b=22&d=24
a=31&c=33&d=34
b=41&c=43&d=44
After log conversion json
[{"a":11,"b":12,"c":13,"d":14},{"a":21,"b":22,"d":14},{"a":31,"c":33,"d":34},{"b":41,"c":43,"d":44}]
@litao09h Sorry but I don't understand. I was asking what is the JSON to which you apply the query #(query%"*abc*")#.[resp.vid,resp.uid,resp.text,resp.errorno]
. The one above doesn't seem to match at all your query.
A default value can be ensured by using the [key,!"default"].0
pattern.
This uses a multipath array to put the key
value into the first position of an array, and a literal value !"default"
as the second, then uses a .0
path to select the first item in the array. Which will either be key
if it exists, or !"default"
if key does not exist.
To get the results @DMLfor is looking for in their original question.
friends.#.[first,!null].0 >> ["Dale",null,"Jane"]
friends.#.others.#.[k,!null].0 >> [["v","v"],[null,"v"],["v",null]]
friends.#.others.#.[k,!null].0
is basically the same as what @volans- used in his example above
friends.#.others.#.[{"k":!null},{k}].@join.@values|#.@flatten
but it may be is a little easier to disect.
A default value can be ensured by using the
[key,!"default"].0
pattern.This uses a multipath array to put the
key
value into the first position of an array, and a literal value!"default"
as the second, then uses a.0
path to select the first item in the array. Which will either bekey
if it exists, or!"default"
if key does not exist.To get the results @DMLfor is looking for in their original question.
friends.#.[first,!null].0 >> ["Dale",null,"Jane"] friends.#.others.#.[k,!null].0 >> [["v","v"],[null,"v"],["v",null]]
That works for me ! Thank you for your patient answer
Current results:
With default value:
Thanks:)