0

I'm trying to save some values from a bash-array into an existing json. I tried some different approaches, but I didn't manage to solve the issue. What am I missing here?

input.json

{
"type": "FeatureCollection",
"name": "test",
"features": [
{ "type": "Feature", "properties": { "OBJECTID": 3213, "USE": "dem", "tile": "4045644"}},
{ "type": "Feature", "properties": { "OBJECTID": 3214, "USE": "dem", "tile": "4045646"}},
{ "type": "Feature", "properties": { "OBJECTID": 3215, "USE": "dem", "tile": "4045648"}}
]
}

Output of some calculations in Bash - 100% derived from input.json. So this array length == length of the "features[]"-array in the input.json

printf '%s\n' "${pushintojson[@]}"

4045646 NV NV NV 
4045648 NV 4045644 NV 
4045650 NV 4045646 NV 
jq '.features |= map(.properties +=  {NOSW: $ARGS.positional})' --args "${pushintojson[@]}"  <<< "${input.json}"

So this produces this (newlines added by me for readability):

{
"type":"FeatureCollection",
"name":"test",
"features": [
{"type":"Feature","properties":{"OBJECTID":3213,"USE":"dem","tile":"4045644",
"NOSW":[
"4045646 NV NV NV",
"4045648 NV 4045644 NV",
"4045650 NV 4045646 NV"
]}},

{"type":"Feature","properties":{"OBJECTID":3214,"USE":"dem","tile":"4045646",
"NOSW":[
"4045646 NV NV NV",
"4045648 NV 4045644 NV",
"4045650 NV 4045646 NV"
]}},

{"type":"Feature","properties":{"OBJECTID":3215,"USE":"dem","tile":"4045648",
"NOSW":[
"4045646 NV NV NV",
"4045648 NV 4045644 NV",
"4045650 NV 4045646 NV"
]}}
]
}

All values of the bash-array are saved to EVERY element. It's supposed to be just one value per json-object - actually as an array itself. So in pseudo: "pushintojson[0]" needs to be under "features[0]", pushintojson[1]" to "features[1]" pushintojson[2]" to "features[2]" etc.

DESIRED OUTPUT

{
"type":"FeatureCollection",
"name":"test",
"features": [
{"type":"Feature","properties":{"OBJECTID":3213,"USE":"dem","tile":"4045644",
"NOSW":"4045646 NV NV NV"
}},
{"type":"Feature","properties":{"OBJECTID":3214,"USE":"dem","tile":"4045646",
"NOSW":"4045648 NV 4045644 NV"
}},
{"type":"Feature","properties":{"OBJECTID":3215,"USE":"dem","tile":"4045648",
"NOSW":"4045650 NV 4045646 NV"
}}
]
}
3
  • Chances are you could do it all in jq to begin with; how do you generate the array? Commented Feb 13, 2022 at 23:37
  • That would be pretty ugly I guess. I'm already struggling with the simpler tasks. Commented Feb 14, 2022 at 7:30
  • Example: 4045648 needs to be stripped to 404 and 5648 as integer. Every entry does have 4 "neighbors", where there values are derived from this value --> (404+2|5648 ; 404-2|5648 ; 404|5648+2 ; 404|5648-2). Then this calculated values needs to be checked if they are part of the overall (feature) list. If not one or all the values become "NV". In fact this values represent a geographical grid of square tiles at a certain extent. Some of them are positioned at the border of the extent (at least 1 NV, because no neighbor-tile) Commented Feb 14, 2022 at 7:41

1 Answer 1

1

If you only use map then for each element you end up iterating over all arguments again. Instead, you have to align the .features array to the $ARGS.positional array.

One way, which is closer to your attempt, is to expand the .features array using to_entries to fit the array's elements with their keys, which in turn can be used within map to reference by index the corresponding item of the $ARGS.positional array.

jq '
  .features |= (to_entries | map(
    .value * {properties: {NOSW: $ARGS.positional[.key]}}
  ))
' --args "${pushintojson[@]}" < input.json

Another approach would be to use transpose to generate an array of aligned items from both initial arrays, and then again just map their contents together.

jq '
  .features |= ([., $ARGS.positional] | transpose | map(
    .[0] * {properties: {NOSW: .[1]}}
  ))
' --args "${pushintojson[@]}" < input.json

Both produce

{
  "type": "FeatureCollection",
  "name": "test",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "OBJECTID": 3213,
        "USE": "dem",
        "tile": "4045644",
        "NOSW": "4045646 NV NV NV"
      }
    },
    {
      "type": "Feature",
      "properties": {
        "OBJECTID": 3214,
        "USE": "dem",
        "tile": "4045646",
        "NOSW": "4045648 NV 4045644 NV"
      }
    },
    {
      "type": "Feature",
      "properties": {
        "OBJECTID": 3215,
        "USE": "dem",
        "tile": "4045648",
        "NOSW": "4045650 NV 4045646 NV"
      }
    }
  ]
}
Sign up to request clarification or add additional context in comments.

1 Comment

Wow, thank you for that and the explanations! jq is so weird... I guess I understood the first one - what is happening there.…The 2nd approach... well, I'll dive into that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.