2017-08-16 3 views
-1

J'ai un fichier de données JSON (comme indiqué ci-dessous) et j'essaie de trouver des valeurs de champ.Analyser ou afficher les champs de données JSON à l'aide de l'utilitaire JQ où les noms de champs ont un "-" tiret dans le nom de clé

Cela fonctionne correctement sauf pour les champs si le nom de la clé contient un caractère tiret -.

Comment puis-je obtenir les valeurs de "champ 2", "champ trois" ou "champ three.url" pour l'élément sous content.book1 (en utilisant jq au moins)?

J'ai essayé ce qui suit pour obtenir les valeurs, mais il me donne les erreurs suivantes pour les champs dont le nom de clé contient un tiret - dans son nom. J'ai essayé de reculer le caractère - mais cela n'a pas aidé non plus.

types d'erreur trouvés:

jq: error (at <stdin>:27): null (null) and number (2) cannot be subtracted 
jq: 1 compile error 

jq: error: three/0 is not defined at <top-level> 

jq: error: syntax error, unexpected INVALID_CHARACTER, expecting $end (Unix shell quoting issues?) at <top-level> 

jq: error: syntax error, unexpected INVALID_CHARACTER, expecting FORMAT or QQSTRING_START (Unix shell quoting issues?) at <top-level>, line 1: 

Commandes:

$ cat /tmp/my.data.json 
{ 
    "pages": { 
    "book1": [ 
     "page1", 
     "page2-para1", 
     "page3-para1-sentence1", 
     "page3-para2-sentence3-word4" 
    ] 
    }, 
    "content": { 
    "book1": { 
     "name": "giga", 
     "url": "-", 
     "field1": "value1", 
     "field-2": "value-2", 
     "field-three": { 
     "name": "THIRD", 
     "url": "book1/field-three/", 
     "short-url": "book1/field-three/chota-chetan" 
     }, 
     "authur": { 
     "name": "lori CHUCK", 
     "displayIndex": 4 
     }, 
     "route": "/in-gc/hindi-chini-bhai-bhai" 
    } 
    } 
} 

$ cat /tmp/my.data.json| jq ".pages" 
{ 
    "book1": [ 
    "page1", 
    "page2-para1", 
    "page3-para1-sentence1", 
    "page3-para2-sentence3-word4" 
    ] 
} 

$ cat /tmp/my.data.json| jq ".pages.book1[0]" 
"page1" 

$ cat /tmp/my.data.json| jq ".pages.book1[1]" 
"page2-para1" 

$ cat /tmp/my.data.json| jq ".content" 
{ 
    "book1": { 
    "name": "giga", 
    "url": "-", 
    "field1": "value1", 
    "field-2": "value-2", 
    "field-three": { 
     "name": "THIRD", 
     "url": "book1/field-three/" 
    }, 
    "authur": { 
     "name": "lori CHUCK", 
     "displayIndex": 4 
    }, 
    "route": "/in-gc/hindi-chini-bhai-bhai" 
    } 
} 

$ cat /tmp/my.data.json| jq ".content.book1" 
{ 
    "name": "giga", 
    "url": "-", 
    "field1": "value1", 
    "field-2": "value-2", 
    "field-three": { 
    "name": "THIRD", 
    "url": "book1/field-three/" 
    }, 
    "authur": { 
    "name": "lori CHUCK", 
    "displayIndex": 4 
    }, 
    "route": "/in-gc/hindi-chini-bhai-bhai" 
} 

$ cat /tmp/my.data.json| jq ".content.book1.name" 
"giga" 

$ cat /tmp/my.data.json| jq ".content.book1.field1" 
"value1" 

$ cat /tmp/my.data.json| jq ".content.book1.field-2" 
jq: error (at <stdin>:27): null (null) and number (2) cannot be subtracted 

$ cat /tmp/my.data.json| jq ".content.book1.field-three" 
jq: error: three/0 is not defined at <top-level>, line 1: 
.content.book1.field-three 
jq: 1 compile error 

$ cat /tmp/my.data.json| jq ".content.book1.field-three.url" 
jq: error: three/0 is not defined at <top-level>, line 1: 
.content.book1.field-three.url 
jq: 1 compile error 

$ cat /tmp/my.data.json| jq ".content.book1.field\-2"  
jq: error: syntax error, unexpected INVALID_CHARACTER, expecting $end (Unix shell quoting issues?) at <top-level>, line 1: 
.content.book1.field\-2      
jq: 1 compile error 

$ cat /tmp/my.data.json| jq ".content.book1.field\\-2" 
jq: error: syntax error, unexpected INVALID_CHARACTER, expecting $end (Unix shell quoting issues?) at <top-level>, line 1: 
.content.book1.field\-2      
jq: 1 compile error 

$ cat /tmp/my.data.json| jq ".content.book1.'field-2'" 
jq: error: syntax error, unexpected INVALID_CHARACTER, expecting FORMAT or QQSTRING_START (Unix shell quoting issues?) at <top-level>, line 1: 
.content.book1.'field-2'    
jq: 1 compile error 

$ cat /tmp/my.data.json| jq ".content.book1.authur" 
{ 
    "name": "lori CHUCK", 
    "displayIndex": 4 
} 

$ cat /tmp/my.data.json| jq ".content.book1.route" 
"/in-gc/hindi-chini-bhai-bhai" 

$ 

PS: Je sais déjà egrep de sorte que ce n'est pas ce que je cherche.

cat /tmp/my.data.json| jq ".content.book1"|egrep "short-url|field-2" 
    "field-2": "value-2", 
    "short-url": "book1/field-three/chota-chetan" 

et quelqu'un a vraiment fait un excellent travail ici: https://jqplay.org/

+0

a ouvert un problème si elle est valide: https://github.com/stedolan/jq/issues/1464 –

+0

Cette question a été posée, par exemple à https://stackoverflow.com/questions/37344329 – peak

+0

Copie possible de [jq ne fonctionne pas sur le nom de l'étiquette avec des tirets] (https://stackoverflow.com/questions/37344329/jq-not-working-on-tag-name -with-dashes) – peak

Répondre

4

"-" est utilisé pour la négation en jq. Pour les noms de clé avec des caractères spéciaux tels que "-", on ne peut pas utiliser la syntaxe simplifiée ".keyname". Il existe plusieurs alternatives, mais la plus robuste consiste simplement à utiliser le formulaire .["KEY NAME"], qui peut être abrégé en ["NOM PRINCIPAL"] lorsqu'il est chaîné, par ex. .a["b-c"] est un raccourci pour .a | .["b-c"].

En cas de doute, utilisez le tuyau explicitement.

Pour plus d'informations, s'il vous plaît consulter le manuel de JQ et/ou https://github.com/stedolan/jq/wiki/FAQ

+0

Nice, je vais accepter cela comme une réponse, mais merci à tous. –

1

Je ne sais pas JQ, mais vous mettez python dans les tags:

$ cat test.json | python -c "import sys, json; print(json.load(sys.stdin)['content']['book1']['field-three']['name'])" 
THIRD 

ou sans tuyau :

$ python -c "import json; print(json.load(open('test.json'))['content']['book1']['field-three']['name'])" 
+0

Merci Alex; avec Python, j'ai déjà utilisé la même solution comme vous l'avez dit, mais je me demande ce qui est mauvais dans 'jq' :) et pourquoi il me donne une erreur pour une opération aussi simple –

+0

Voter comme c'est un bon doublure. –

1

Comme expliqué dans le jq manual, à gérer les clés avec des caractères non-identifiant comme - vous pouvez utiliser des guillemets doubles.

À partir du shell, ceci est plus facile si vous utilisez des guillemets simples autour de votre filtre. Par exemple, essayez les commandes suivantes:

cat /tmp/my.data.json | jq '.pages' 
cat /tmp/my.data.json | jq '.pages.book1[0]' 
cat /tmp/my.data.json | jq '.pages.book1[1]' 
cat /tmp/my.data.json | jq '.content' 
cat /tmp/my.data.json | jq '.content.book1' 
cat /tmp/my.data.json | jq '.content.book1.name' 
cat /tmp/my.data.json | jq '.content.book1.field1' 
cat /tmp/my.data.json | jq '.content.book1."field-2"' 
cat /tmp/my.data.json | jq '.content.book1."field-three"' 
cat /tmp/my.data.json | jq '.content.book1."field-three".url' 
cat /tmp/my.data.json | jq '.content.book1.authur' 
cat /tmp/my.data.json | jq '.content.book1.route' 
+0

merci, très utile. –

0

Hm..took un peu de temps mais finalement il semble que nous devons Guillemet et barre oblique inverse juste le guillemet pour une touche nom contenant un - dans son nom.

$ cat /tmp/my.data.json| jq ".content.book1.\"field-2\""      
"value-2" 

$ cat /tmp/my.data.json| jq ".content.book1.\"field-three\".\"url\"" 
"book1/field-three/" 

OU si vous enveloppez tout dans un seul devis ', nous ne devons pas backslasher " guillemets doubles mais utiliser des guillemets pour les noms clés avec - en leur nom.

$ cat /tmp/my.data.json| jq '.content.book1."field-three"."url"' 
"book1/field-three/" 

Espérons que ça aide! A pris un peu d'aide/soupçon de https://jqplay.org/

Voir ce pour plus: https://github.com/stedolan/jq/issues/38#issuecomment-9770240