Comment convertir une chaîne json incorporée (citée) en json

22

Je connais "jq" pour analyser json.

Je travaille avec un service qui produit une réponse json où l'une des propriétés est elle-même une chaîne json. Comment convertir cette valeur entre guillemets en une chaîne json valide afin de pouvoir ensuite la traiter avec jq?

Par exemple, si je regarde simplement le json joliment imprimé de "jq.", Voici un court extrait de la sortie:

"someJsonString": "{\"date\":\"2018-01-08\", ...

Je peux utiliser jq pour obtenir la valeur de cette propriété, mais je dois convertir la chaîne entre guillemets en json valide en la "décompressant".

Je suppose que je pourrais le diriger vers sed, en supprimant les guillemets doubles d'ouverture et de fin et en supprimant toutes les barres obliques inverses (" sed -e 's/^"//' -e 's/"$//' -e 's/\\//g'"). Cela semble fonctionner, mais cela ne semble pas être la solution la plus robuste.

Mise à jour :

Juste pour être un peu plus clair sur ce que je fais, voici quelques exemples élidés qui montrent ce que j'ai essayé:

% curl -s -q -L 'http://.../1524.json' | jq '.results[0].someJsonString' | jq .
"{\"date\":\"2018-01-08\",...
% echo $(curl -s -q -L 'http:/.../1524.json' | jq '.results[0].someJsonString') | jq .
"{\"date\":\"2018-01-08\",...

Mise à jour :

Voici un exemple complètement autonome:

% cat stuff.json | jq .
{
  "stuff": "{\"date\":\"2018-01-08\"}"
}
% cat stuff.json | jq '.stuff'
"{\"date\":\"2018-01-08\"}"
% cat stuff.json | jq '.stuff' | jq .
"{\"date\":\"2018-01-08\"}"

Mise à jour :

Si j'ai essayé de traiter cette dernière sortie avec une véritable expression jq, cela fait quelque chose comme ceci:

% cat stuff.json | jq '.stuff' | jq '.date'
assertion "cb == jq_util_input_next_input_cb" failed: file "/usr/src/ports/jq/jq-1.5-3.x86_64/src/jq-1.5/util.c", line 371, function: jq_util_input_get_position
Aborted (core dumped)
David M. Karr
la source
Si vous utilisez jqpour obtenir uniquement la valeur de la propriété de chaîne, la renvoie-t-elle sans échappement? Si c'est le cas, il vous suffit de le canaliser dans un nouveau jq.
DopeGhoti
Non, il ne le rend pas sans échappatoire. C'est le but.
David M. Karr
Et alors echo $(jq statement here)?
DopeGhoti
Non, pas de changement.
David M. Karr
@ DavidM.Karr, ok, si possible - étendez votre entrée avec la chaîne cruciale réelle et le résultat final
RomanPerekhrest

Réponses:

20

Il y a un rawdrapeau pour ça

    -r      output raw strings, not JSON texts;

jq -rc .stuff stuff.json

Sortie

{"date":"2018-01-08"}
cricket_007
la source
La différence est qu'avec la réponse de Roman, vous êtes assuré d'obtenir une sortie JSON valide ou des messages d'erreur si ce n'est pas du JSON valide.
Kusalananda
Point valide, mais si cela est utilisé dans l'automatisation, je pense qu'il serait inhabituel de ne pas avoir soudainement une sortie json valide. La forme la plus pratique sera parfaitement fine presque tout le temps. Cependant, il est toujours bon de connaître des méthodes plus précises.
David M. Karr
@ DavidM.Karr "inhabituel de ne pas avoir soudainement une sortie json valide" HA! Riiiight. Gestion des erreurs dans l'automatisation? Les erreurs ne se produiront jamais ! Pourquoi s'embêter!
Bruno Bronosky
Cela nécessite un raccordement à un autre jqpour un traitement JSON ultérieur, tandis qu'avec l'approche de Roman, vous pouvez continuer la même jqexpression.
Raman
1
@ cricket_007: l'a essayé avec jq 1.5, et a confirmé qu'il ne fonctionne pas: jq -rc '.stuff.date'produit jq: error (at <stdin>:0): Cannot index string with string "date". Cependant: .stuff | fromjson | .datefonctionne très bien.
Raman
26

Avec jqla fromjsonfonction:

Exemples de stuff.jsoncontenu:

{
  "stuff": "{\"date\":\"2018-01-08\"}"
}

jq -c '.stuff | fromjson' stuff.json

Le résultat:

{"date":"2018-01-08"}
RomanPerekhrest
la source
Cela semble inutile. Réponse alternative fournie
cricket_007