Welcome to Software Development on Codidact!
Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.
Post History
Consider the following arbitrarily-nested JSON as input to a jq filter: echo '[{"foo": [1, 2]}, {"bar": [{"baz": ["foo", "baz"]}]}]' | jq '.' My goal is to join leaf arrays into strings: [{"fo...
#6: History hidden
Replace leaf arrays with joined strings in a nested structure in jq
Consider the following arbitrarily-nested JSON as input to a jq filter: ```bash echo '[{"foo": [1, 2]}, {"bar": [{"baz": ["foo", "baz"]}]}]' | jq '.' ``` My goal is to join leaf arrays into strings: ```json [{"foo": "12"}, {"bar": [{"baz": "foobaz"}]}] ``` The following filter produces the above output: ```jq walk(if type == "array" and all(type != "array" and type != "object") then join("") else . end) ``` But if I use this filter on an array-only structure like ```json [[1, 2], [[3, 4], [[5, 6], [7]]]] ``` I get: ```json "1234567" ``` Instead of the expected ```json ["12", ["34", ["56", "7"]]] ``` Instead of replacing the leaf arrays with strings, it's reduced the nested structure down to a single string! If I change my filter to ```jq walk(if type == "array" and all(type != "array" and type != "object") then [join("")] else . end) ``` At least the expected structure is preserved, but now the inner strings have an extra single-element array that shouldn't be there: ```json [["12"], [["34"], [["56"], ["7"]]]] ``` It's not feasible to strip off these single-element arrays after the fact, since a second pass won't differentiate a single-element array that's supposed to be there from a temporary artificial one. I suppose I could add some metadata to enable second-pass differentiation, but this seems messy to code and hacky. I feel like there should be a simple, direct solution. I also tried changing my `if` branch to `. = join("")` and `. |= join("")`, but these give me the same old `"1234567"`. How can I reliably join leaf arrays to strings in an arbitrarily-nested structure in-place, without modifying the structure? Why is `walk` flattening arrays but not objects here, anyway?