skip to Main Content

I have the following data :

{
   "storageSummary": "testvalue",
   "audit1": {
         "auditScore": 1,
         "suspensionScore": 1,
         "password" : "value1",
         "onlineScore": 0.99743587,
         "satelliteName": "us2.storj.io:7777"
      },
   "audit2": {
         "auditScore": 1,
         "suspensionScore": 1,
         "password" : "valueX",
         "onlineScore": 0.9992917,
         "satelliteName": "saltlake.tardigrade.io:7777"
      },
   "audit3": {
         "auditScore": 1,
         "suspensionScore": 1,
         "password" : "value72",
         "onlineScore": 0.99930555,
         "satelliteName": "ap1.storj.io:7777"
      }
}

In bash, I need to go through this data, to update the password for all auditX objects.

I’ve tried the following :

jq ' .[] |select(has("auditScore")) '

But I get an error on the first item :

jq: error (at <stdin>:23): Cannot check whether string has a string key
exit status 5

When I remove the first item "storageSummary": "testvalue"in my data, I can loop through my objects (but my data has some items without auditscore keys…)

The final goal is to run this result in a bash for loop to update the password (and do more specific task…)

Could you please point me in the right direction ?

EDIT : Thank you pmf, you made me go forward.

Now, next step (should I open a new thread ?), I’d like to do something like :

DS_OBJECT=$(jq -c ' .[]|select(type == "object" and has("auditScore"))' ${DS_SRC_FILE})

for row in ${DS_OBJECT}; do
    _jq() {
     echo "${row}" | jq -r "${1}"
    }
    echo -e "Working $(_jq '.satelliteName')..."
    # then update $row's password...
done
  • How can I display audit1, the object’s name, instead of the satelliteName in my loop
  • How do I update the password for this object ?

Thank you

2

Answers


  1. You can filter for objects using select(type == "object"), or use its shortcut equivalent objects:

    .[] | select(type == "object" and has("auditScore"))
    # or
    .[] | objects | select(has("auditScore"))
    

    This will return a stream of objects having a field named auditScore

    {
      "auditScore": 1,
      "suspensionScore": 1,
      "password": "value1",
      "onlineScore": 0.99743587,
      "satelliteName": "us2.storj.io:7777"
    }
    {
      "auditScore": 1,
      "suspensionScore": 1,
      "password": "valueX",
      "onlineScore": 0.9992917,
      "satelliteName": "saltlake.tardigrade.io:7777"
    }
    {
      "auditScore": 1,
      "suspensionScore": 1,
      "password": "value72",
      "onlineScore": 0.99930555,
      "satelliteName": "ap1.storj.io:7777"
    }
    

    To set a(nother) field based on that stream, wrap the LHS into parens to keep the context:

    (.[] | select(type == "object" and has("auditScore"))).password = "X"
    # or
    (.[] | objects | select(has("auditScore"))).password = "X"
    
    Login or Signup to reply.
  2. With Ruby:

    ruby -r json -e '
    JSON.parse($<.read).select{|k,v| v.is_a?(Hash) && v.has_key?("auditScore")}.
        each{|k,v| puts "Key: #{k} nValue: #{v}n" }
    ' file 
    

    Prints:

    Key: audit1 
    Value: {"auditScore"=>1, "suspensionScore"=>1, "password"=>"value1", "onlineScore"=>0.99743587, "satelliteName"=>"us2.storj.io:7777"}
    Key: audit2 
    Value: {"auditScore"=>1, "suspensionScore"=>1, "password"=>"valueX", "onlineScore"=>0.9992917, "satelliteName"=>"saltlake.tardigrade.io:7777"}
    Key: audit3 
    Value: {"auditScore"=>1, "suspensionScore"=>1, "password"=>"value72", "onlineScore"=>0.99930555, "satelliteName"=>"ap1.storj.io:7777"}
    

    If you want to change the password of each:

    ruby -r json -e '
    puts JSON.pretty_generate(JSON.parse($<.read).
        each{|k,v| if v.is_a?(Hash) && v.has_key?("auditScore") 
        then
            v["password"]="XXX"
        end
    })
    ' file 
    

    Prints:

    {
      "storageSummary": "testvalue",
      "audit1": {
        "auditScore": 1,
        "suspensionScore": 1,
        "password": "XXX",
        "onlineScore": 0.99743587,
        "satelliteName": "us2.storj.io:7777"
      },
      "audit2": {
        "auditScore": 1,
        "suspensionScore": 1,
        "password": "XXX",
        "onlineScore": 0.9992917,
        "satelliteName": "saltlake.tardigrade.io:7777"
      },
      "audit3": {
        "auditScore": 1,
        "suspensionScore": 1,
        "password": "XXX",
        "onlineScore": 0.99930555,
        "satelliteName": "ap1.storj.io:7777"
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search