7 votes

jq : erreur (at <stdin>:0) : Cannot iterate over null (null)

J'ai travaillé sur un appel API pour le structurer au format JSON afin de pouvoir le pousser plus tard dans une base de données. Le code ressemble alors à ceci :

getPage() {
curl --fail -X GET 'https://api.app.com/v1/test?page=1&pageSize=1000&sort=desc' \
  -H 'Authorization: Bearer 123abc456pickupsticks789' \
  -H 'cache-control: no-cache'  
}

getPage \
| jq -c '.items | .[] | {landing_id: .landing_id, submitted_at: .submitted_at, answers: .answers, email: .hidden.email}' \
  > testpush.json

Cependant, lorsque je l'exécute, il produit cette erreur : jq: error (at <stdin>:0): Cannot iterate over null (null)

J'ai examiné des solutions telles que celui-ci , ou celui de ce site et cette réponse.

La solution la plus courante semble être d'utiliser un ? devant [] et je l'ai essayé dans le jq vers le bas, mais cela ne fonctionne toujours pas. Il produit juste un fichier json vide.

Ai-je mal interprété les conclusions de ces autres réponses et n'ai-je pas mis mon ? au bon endroit ?

14voto

peak Points 71

Pour se protéger contre la possibilité que .items n'est pas un tableau, vous pourriez écrire :

.items | .[]?

ou même de manière plus robuste :

try .items[]

ce qui est équivalent à (.items[])? .

En résumé :

  • try E est équivalent à try E catch empty
  • try E est équivalent à (E)?

(Notez que les expressions .items[]? et (.items[])? ne sont pas identiques).

Cependant, aucune de ces solutions ne permet de se protéger contre les entrées qui sont des JSON invalides.


p.s. A l'avenir, veuillez suivre les directives de mcve ( http://stackoverflow.com/help/mcve ) ; dans le cas présent, il aurait été utile de fournir un extrait JSON à titre d'exemple, basé sur la sortie produite par la fonction curl commandement.

1voto

Thiago Conrado Points 104

Il est nécessaire de faire savoir à JSON qu'il peut continuer après une valeur inattendue lors de l'analyse de ce tableau. essayez ou ? sont des options parfaites pour cela.

N'oubliez pas qu'il est nécessaire de garantir les données ou de faire savoir à l'interprète qu'il peut continuer. Cela peut sembler redondant, mais il s'agit d'une sorte d'approche de sécurité pour éviter les résultats inattendus qui sont plus difficiles à suivre/à remarquer. Il est également nécessaire d'être conscient des différences en matière de "test" entre ? vs essayer .

En supposant que $sample respecte les normes JSON, le code ci-dessous fonctionnera toujours :

sample='{"myvar":1,"var2":"foo"}'
jq '{newVar: ((.op[]? | .item) // 0)}' <<< $sample

donc, le op Le tableau est null pour $sample comme ci-dessus, mais il est clair pour jq qu'il peut continuer sans demander votre intervention/réparation.


Mais si vous assumez ? comme la même chose que essayez vous pouvez obtenir une erreur (il m'a fallu beaucoup de temps pour apprendre cela, et ce n'est pas clair dans la documentation). Comme exemple d'utilisation incorrecte de ? nous avons :

sample='{"myvar":1,"var2":"foo"}'
jq '{newVar: (.op[].item? // 0)}' <<< $sample

Donc, comme op est null cela conduira à une erreur, car vous dites à jq d'ignorer une erreur lors de la récupération .item tandis qu'il est fait mention de la possibilité d'une erreur lors de la tentative d'itération sur null (dans ce cas .op[] ), et cette tentative s'est produite avant ce point de vérification de la présence de .item . D'autre part, essayer fonctionnerait dans ce cas :

sample='{"myvar":1,"var2":"foo"}'
jq '{newVar: (try .op[].item catch 0)}' <<< $sample

Il s'agit d'une petite différence d'utilisation qui peut entraîner une grande différence dans le résultat.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X