web-dev-qa-db-fra.com

Comment transformer un fichier JSON valide en fichier CSV?

J'essaie d'extraire des informations d'un fichier JSON et d'écrire une partie du contenu dans un fichier CSV.

Voici un exemple de mon texte

"data":{"headers":{"sender":"[email protected]"
"to":"[email protected]"
"subject":"Help with this project"
"x-received-time":"14144273245408"
"received":"from abc.com ()\r\n        by mail.mail.com with SMTP (Postfix)\r\n        for [email protected];\r\n        Mon
"from":"\"Help with this project\" <[email protected]>"
"date":"Mon, 27 Oct 2014 09:03:14 -0500"
"id":"1414427328-2345855-frank"
"to":"[email protected]"
"time":14144273245408
"subject":"Help with this project"
"fromfull":"[email protected]"

Je veux récupérer le contenu de: to, fromfull, id, subject, date et l'écrire dans un fichier csv où To correspond à la colonne A, fromfull à la colonne B, etc.

Quelqu'un peut-il offrir une assistance? Ceci est une réponse JSON.

6
BeMy Friend

Vous pouvez utiliser la commande Perl suivante pour créer la sortie CSV, ouvrir un terminal et taper:

Perl -n0e '@a= $_ =~ /"date":(".*?").*?"id":(".*?").*?"to":"(.*?)".*?".*?"subject":(".*?").*?"fromfull":"(.*?)"/gs;  while (my @next_n = splice @a, 0, 5) { print join(q{,}, @next_n)."\n"}' inputfile.txt

Cela fonctionnera même si vous avez plusieurs en-têtes dans votre fichier d'entrée.

Notez que seul le dernier champ "à": est pris en compte (il semble que vos en-têtes fournissent les informations deux fois)

Le résultat de la commande:

"Mon, 27 Oct 2014 09:03:14 -0500","1414427328-2345855-frank",[email protected],"Help with this project",[email protected]
8
Sylvain Pineau

Vous pouvez convertir ce fichier JSON en fichier CSV sur une seule ligne avec jq .

jq '.data.headers | [.sender, .to, .subject, ."x-received-time", 
.received, .from, .date, .id, .to, .subject, .fromfull] 
+ [(.time | tostring)] | join(", ")'

Panne:

  • .data.headers - Emet des en-têtes en tant qu'objet
    • Si les données contiennent un tableau d'en-têtes, ce serait .data[].headers
  • […string keys list…] - Émettre des valeurs de chaîne sous forme de tableau
  • + [(.time | tostring)] - Emet du temps sous forme de chaîne et ajoute au tableau
  • join(", ") - Joignez les valeurs du tableau en utilisant une virgule et un espace
    • Remplacez votre délimiteur préféré ici
8
Joe Harris

Puisque vous travaillez avec des fichiers JSON, pourquoi ne pas l’analyser comme tel? Installez nodejs-legacy et créez un script NodeJS tel que:

#!/usr/bin/env node
// parseline.js process lines one by one
'use strict';
var readline = require('readline');
var rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
  terminal: false
});

rl.on('line', function(line){
    var obj = JSON.parse(line);
    // add the fields which you want to extract here:
    var fields = [
        obj.data.headers.to,
        obj.data.headers.subject,
        // etc.
    ];
    // print the fields, joined by a comma (CSV, duh.)
    // No escaping is done, so if the subject contains ',',
    // then you need additional post-processing.
    console.log(fields.join(','));
});

En supposant que vous ayez une chaîne JSON valide sur chaque ligne d'un fichier:

node parseline.js < some.txt

Ou si vous voulez vraiment lire un seul fichier et analyser les champs de celui-ci:

#!/usr/bin/env node
// parsefile.js - fully read file and parse some data out of it
'use strict';
var filename = process.argv[1]; // first argument
var fs = require('fs');
var text = fs.readFileSync(filename).toString();
var obj = JSON.parse(text);
// add the fields which you want to extract here:
var fields = [
    obj.data.headers.to,
    obj.data.headers.subject,
    // etc.
];
// print the fields, joined by a comma (CSV, duh.)
// No escaping is done, so if the subject contains ',',
// then you need additional post-processing.
console.log(fields.join(','));

Puis lancez-le avec:

node parsefile.js yourfile.json > yourfile.csv
6
Lekensteyn

Vous pouvez utiliser jsonv de GitHub

Et ensuite la commande suivante:

cat YOUR_JSON_FILEname | jsonv to,fromfull,id,subject,date > output.csv
1
Edward Moffett

Voici une awk implémentation:

   awk -F ":" '{gsub("\"","",$1);key=$1;sub(key " ","");gsub("\\","",$0);value[key]=$0; if ("fromfull"== key) print value["from"] ";" value["to"] ";" value["fromfull"] ";" value["id"] ";" value["subject"] ";" value["date"] ;}' jsonFile > csvFile

Ce script lit la ligne jusqu'à ce qu'elle trouve la ligne "fromfull", puis affiche la ligne csvname__, de sorte qu'elle devrait également fonctionner avec plusieurs séquences.

Voici le résultat:

  ""Help with this project" <[email protected]>";"[email protected]";"[email protected]";"1414427328-2345855-frank";"Help with this project";"Mon, 27 Oct 2014 09 03 14 -0500"
1
Lety

Voici un script gawk que je viens de fouetter pour vous!

#!/usr/bin/gawk -f
BEGIN {
  FS="\""
  output=""
  nodata=1
}

/^"data"/{
  if( ! nodata )
  {
    gsub("|$","",output)
    print output
    nodata=0
  }
  output=""
}

/^"[^d][^a][^t][^a]/{
  if ( $2 == "to" || $2 == "fromfull" || $2 == "id" || $2 == "subject" || $2 == "date" )
    output=output$4"|"
}

END{
  gsub("|$","",output)
  print output
}

Cela devrait fonctionner sur un fichier avec un tas d'entrées similaires. Si vous souhaitez ajouter d'autres éléments à la liste, ajoutez-les simplement dans l'instruction if. J'ai cependant trouvé un problème avec votre ensemble de données: les dates. Ils contiennent des virgules, donc ce ne peut pas être un vrai CSV. Au lieu de cela, je l'ai juste séparé avec un autre personnage.

1
Chuck R