Как преобразовать допустимый JSON к CSV?

Я пытаюсь извлечь информацию из файла JSON и записать часть содержания к файлу CSV.

Вот пример моего текста

"data":{"headers":{"sender":"frank@abc.com"
"to":"jim@def.com"
"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 jim@def.com;\r\n        Mon
"from":"\"Help with this project\" <frank@abc.com>"
"date":"Mon, 27 Oct 2014 09:03:14 -0500"
"id":"1414427328-2345855-frank"
"to":"jim@def.com"
"time":14144273245408
"subject":"Help with this project"
"fromfull":"frank@abc.com"

Я хочу захватить содержание от: к, fromfull, идентификатор, предмет, дата и запись это к файлу CSV, где К столбец A, fromfull, является столбец B и т.д.

Кто-либо может предложить помощь? Это - ответ JSON.

6
задан 25 June 2015 в 14:25

6 ответов

Можно использовать следующую команду жемчуга, чтобы создать вывод CSV, открыть терминал и тип:

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

Это будет работать, даже если у Вас будет несколько заголовков в Вашем входном файле.

Обратите внимание что только последнее "к": поле принято во внимание (кажется, что Ваши заголовки обеспечивают информацию дважды),

Команда произвела:

"Mon, 27 Oct 2014 09:03:14 -0500","1414427328-2345855-frank",jim@def.com,"Help with this project",frank@abc.com
8
ответ дан 23 November 2019 в 07:14

Можно преобразовать этот JSON в CSV в одной строке с jq .

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

Разбивка:

  • .data.headers - Испускают заголовки как объект
    • , Если бы данные содержали массив заголовков, то это было бы .data[].headers
  • […string keys list…] - Испускают строковые значения, поскольку массив
  • + [(.time | tostring)] - Испускает время как строку и добавляет к массиву
  • join(", ") - Соединение значения массива с помощью запятой и пространства
    • Замена любимый разделитель здесь
10
ответ дан 23 November 2019 в 07:14

Можно использовать jsonv от GitHub

И затем следующей команды:

cat YOUR_JSON_FILEname | jsonv to,fromfull,id,subject,date > output.csv
2
ответ дан 23 November 2019 в 07:14

Вот сценарий простофили, который я просто сделал на скорую руку для Вас!

#!/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
}

Это должно работать над файлом с набором подобных записей. Если Вы хотите добавить другие объекты к списку, просто включите их если оператор. Я действительно находил одну проблему с Вашим набором данных хотя: даты. Они содержат запятые, таким образом, это не может быть истинный CSV. Вместо этого я просто разделил его с другим символом.

1
ответ дан 23 November 2019 в 07:14

Так как Вы работаете с файлами JSON, почему бы не проанализировать его как таковой? Установка nodejs-legacy и создайте сценарий NodeJS, такой как:

#!/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(','));
});

Принятие Вас имеет допустимую строку JSON на каждой строке файла:

node parseline.js < some.txt

Или если Вы действительно хотите считать единственный файл и поля синтаксического анализа от этого:

#!/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(','));

Затем выполните его с:

node parsefile.js yourfile.json > yourfile.csv
6
ответ дан 23 November 2019 в 07:14

Вот awk реализация:

   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

Этот сценарий считал строку, пока не найдено "fromfull" строка, чем печать csv строка, таким образом, это должно работы также с несколькими последовательностями.

Это - результат:

  ""Help with this project" <frank@abc.com>";"jim@def.com";"frank@abc.com";"1414427328-2345855-frank";"Help with this project";"Mon, 27 Oct 2014 09 03 14 -0500"
1
ответ дан 23 November 2019 в 07:14

Другие вопросы по тегам:

Похожие вопросы: