skip to Main Content

I am processing a large json structure which is in foo.json

at the completion of this filter
jq '.[] | select(.entity_id|test("sensor.current.")) | { (.entity_id) : .state} ' foo.json
having reduced the list of components with a select() I get:

{
  "sensor.current_consumption": "1.4"
}
{
  "sensor.current_power": "194.6"
}
{
  "sensor.current_mains_voltage": "239.9"
}

What I want is
{ "sensor.current_consumption": "1.4", "sensor.current_power": "194.6", "sensor.current_mains_voltage": "239.9" }

I have tried to read up on jq’s map() and add() but cannot make much sense. Similar questions have been asked before and looking at answers e.g. here I tried

jq '.[] | select(.entity_id|test("sensor.current.")) | map({ (.entity_id) : .state}) | add   ' foo.json
jq: error (at foo.json:0): Cannot index string with string "entity_id"

and

jq '.[] | select(.entity_id|test("sensor.current.")) | map({ (.entity_id) : .state}) | add   ' foo.json
rrent.")) | map({ (.entity_id) : .state}) | add   ' foo.foo

Any help is welcome

2

Answers


  1. Don’t iterate the elements of the array with .[] but map them to a new array, then add them to a single object:

    map(select(.entity_id|startswith("sensor.current.")) | { (.entity_id) : .state})
    | add
    

    Alternatively, reduce to your final object:

    reduce (.[] | select(.entity_id|startswith("sensor.current.")))
    as $x ({}; .[$x.entity_id] = $x.state)
    

    The third option is using from_entries to construct an object from an array of key-value-pairs:

    map(select(.entity_id|startswith("sensor.current.")) | { key: .entity_id, value: .state})
    | from_entries
    
    Login or Signup to reply.
  2. If your input is large, you may want to use reduce to iteratively build up your output object:

    … | reduce (.[] | select(.entity_id | test("sensor.current."))) as $item ({};
          .[$item.entity_id] = $item.state
        )
    

    Note that test works with regular expressions, so the . in "sensor.current." means any character. You might want to use contains or startswith instead.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search