Jq Filtering - Cannot Index Array with String "Score"

Jq Filtering - Cannot Index Array with String "Score"

I am trying to find person name who has a subject and it score. But i am getting index arrary.

jq -r '.[] | select(.result."*value*".Score.English) | {Name: .result."*value*".name, Subject: .result."*value*".Score.English} | @text' test.txt | sed 's/^{\|}$//g; s/,/\n/'

INPUT JSON FILE

[{
    "host": "testserver",
    "hostclass": "Unknown",
    "result": {
        "*value*": [
            {
                "sessionId": "000001",
                "name": "ABC",
                "Age": "21",
                "Score": {
                    "English": "A+",
                    "Mathematics": "B-",
                    "String Theory": "C+"
                }
            },
            {
                "sessionId": "000001",
                "name": "CDE",
                "Age": "21",
                "Score": {
                    "English": "A-",
                    "German": "B-",
                    "French": "C+"
                }
            },
            {
                "sessionId": "000001",
                "name": "EFG",
                "Age": "21",
                "Score": {
                }
            },
            {
                "sessionId": "000001",
                "name": "XYZ",
                "Age": "21"
            }]
   }
}]

OUTPUT :

Name: ABC
Subject : A+
Name: CDE
Subject : A-

ERROR :

jq: error (at test.txt:39): Cannot index array with string "Score"

how can i fix this error

2 Answers

You need to iterate through the "*value*" children with "*value*"[]. Here is a solution that I tested and it produces the output you want:

cat test.txt | jq -r '.[].result."*value*"[] | select(.Score.English) | "Name: "+.name+"\nSubject: "+.Score.English'

I'm surprised no one gave you a jq solution on this one so far. Then, instead, let me give you an alternative one - based on unix walk-path utility jtc:

bash $ <input.json jtc -w'<English>l:[-2][name]' -w'<English>l:' -l
"name": "ABC"
"English": "A+"
"name": "CDE"
"English": "A-"
bash $ 

And if you really meant to replace "English" with "Subject", then add template per each walk, like this:

bash $ <input.json jtc -w'<English>l:[-2][name]' -w'<English>l:' -TT -T'{"Subject":"{}"}' -ll
"name": "ABC"
"Subject": "A+"
"name": "CDE"
"Subject": "A-"
bash $ 
  • first template (-TT) is a dummy one, meant to fail (because first walk does not require altering)

btw, there's a bit more succinct way of writing the same query:
<input.json jtc -x'<English>l' -y:[-2][name] -y: -TT -T'{"Subject":"{}"}' -ll

PS> Disclosure: I'm the creator of the jtc - shell cli tool for JSON operations

EDIT: another way to achieve the same query:

bash $ <input.json jtc -w'<English>l:<N>v[-2][name]' -llT'{"Name":{{}},"Subject":{{N}}}'
"Name": "ABC"
"Subject": "A+"
"Name": "CDE"
"Subject": "A-"
bash $ 

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Sophia Al-Mansoor
Author

Sophia Al-Mansoor

Sophia analyzes international trade, startup ecosystems, retail transformation, and supply chain logistics for modern digital publications.