如何将动态 JSON 之类的文件转换为 CSV 文件

How to convert a dynamic JSON like file to a CSV file

我有一个文件,与下图完全一样。

{"eventid" : "12345" ,"name":"test1","age":"18"}
{"eventid" : "12346" ,"age":"65"}
{"eventid" : "12336" ,"name":"test3","age":"22","gender":"Male"}

将上述文件视为 event.json

每行的数据对象数量可能不同。 我想要以下 csv 输出。它将是 output.csv

eventid,name,age,gender
12345,test1,18
12346,,65
12336,test3,22,Male

有人可以帮助我吗?我可以接受来自任何脚本语言(Javascript、Python 等)的答案。

var arr = $.map(obj, function(el) { return el });
var content = "";
for(var element in arr){
    content += element + ",";
}

var filePath = "someFile.csv";
var fso = new ActiveXObject("Scripting.FileSystemObject");
var fh = fso.OpenTextFile(filePath, 8, false, 0);
fh.WriteLine(content);
fh.Close();

这是一个 Python 解决方案(应该适用于 Python 2 和 3)。 我对这些代码并不感到自豪,因为可能有更好的方法来执行此操作(使用 csv 模块),但这会为您提供所需的输出。

我冒昧地将你的 JSON 数据命名为 data.json 并且我将输出的 csv 文件命名为 output.csv.

import json

header = ['eventid', 'name', 'age', 'gender']

with open('data.json', 'r') as infile, \
     open('outfile.csv', 'w+') as outfile:

    # Writes header row
    outfile.write(','.join(header))
    outfile.write('\n')

    for row in infile:
        line = ['', '', '', ''] # I'm sure there's a better way
        datarow = json.loads(row)

        for key in datarow:
            line[header.index(key)] = datarow[key]

        outfile.write(','.join(line))
        outfile.write('\n')

希望这对您有所帮助。

此代码将动态收集所有 headers 并将文件写入 CSV。

阅读代码中的注释了解详情:

import json

# Load data from file
data = '''{"eventid" : "12345" ,"name":"test1","age":"18"}
{"eventid" : "12346" ,"age":"65"}
{"eventid" : "12336" ,"name":"test3","age":"22","gender":"Male"}'''

# Store records for later use
records = [];

# Keep track of headers in a set
headers = set([]);

for line in data.split("\n"):
    line = line.strip();

    # Parse each line as JSON
    parsedJson = json.loads(line)

    records.append(parsedJson)

    # Make sure all found headers are kept in the headers set
    for header in parsedJson.keys():
        headers.add(header)

# You only know what headers were there once you have read all the JSON once.

#Now we have all the information we need, like what all possible headers are.

outfile = open('output_json_to_csv.csv','w')

# write headers to the file in order
outfile.write(",".join(sorted(headers)) + '\n')

for record in records:
    # write each record based on available fields
    curLine = []
    # For each header in alphabetical order
    for header in sorted(headers):
        # If that record has the field
        if record.has_key(header):
            # Then write that value to the line
            curLine.append(record[header])
        else:
            # Otherwise put an empty value as a placeholder
            curLine.append('')
    # Write the line to file
    outfile.write(",".join(curLine) + '\n')

outfile.close()

这是一个使用 jq 的解决方案。

如果filter.jq包含以下过滤器

  (reduce (.[]|keys_unsorted[]) as $k ({};.[$k]="")) as $o   # object with all keys
| ($o  | keys_unsorted), (.[] | $o * . | [.[]])              # generate header and data
| join(",")                                                  # convert to csv

data.json包含示例数据然后

$ jq -Mrs -f filter.jq data.json

生产

eventid,name,age,gender
12345,test1,18,
12346,,65,
12336,test3,22,Male

将 Angularjs 与 ngCsv 插件结合使用,我们可以使用动态 headers 从所需的 json 生成 csv 文件。

Run in plunkr

// Code goes here

 var myapp = angular.module('myapp', ["ngSanitize", "ngCsv"]);

 myapp.controller('myctrl', function($scope) {
   $scope.filename = "test";
   $scope.getArray = [{
     label: 'Apple',
     value: 2,
     x:1,
   }, {
     label: 'Pear',
     value: 4,
     x:38
   }, {
     label: 'Watermelon',
     value: 4,
     x:38
   }];


   $scope.getHeader = function() {
    var vals = [];
    for( var key in $scope.getArray ) {
    for(var k in $scope.getArray[key]){
      vals.push(k);
     }
     break;
    }
    return vals;
    
   };

 });
<!DOCTYPE html>
<html>
  <head>
    <link href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet">

    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.min.js"></script>

   <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular-sanitize.min.js"></script>
   
 <script src="https://cdnjs.cloudflare.com/ajax/libs/ng-csv/0.3.6/ng-csv.min.js"></script>
   

  </head>


  <body>

    <div ng-app="myapp">

      <div class="container" ng-controller="myctrl">

        <div class="page-header">

          <h1>ngCsv <small>example</small></h1>

        </div>
       
        

        <button class="btn btn-default" ng-csv="getArray" csv-header="getHeader()" filename="{{ filename }}.csv" field-separator="," decimal-separator=".">Export to CSV with header</button>

       
      </div>
    </div>
  </body>
</html>