如何使用 python 或 jq 将具有统一列的多个 JSON 文件合并为一个 CSV?
How do I use python or jq to merge multiple JSON files with uniform columns into one CSV?
我正在努力使主要来源美国法律更符合美国残疾人法案 (ADA),更符合我的研究。
技术问题在主题中。
我正在使用的源文件可以在这里找到:https://www.courtlistener.com/api/bulk-data/opinions/wash.tar.gz
该档案中的示例 JSON 文件(其中包含 52,565 条华盛顿州最高法院的司法意见),
987095.json 是一个包含以下“元素”的示例(我想将元素名称作为列名传递,同时为记录计数提供新的 ID;而不是源数据库 ID 列):
使用 Dadroit Viewer 1.5 Build 1935.appimage 查看 JSON 数据对我来说最简单。
我提取了以下数据(底部 opinions_cited 有 [] 括号,其中包含 0 - 28;我希望每个 JSON 都有不同数量的 opinions_cited ;任何人从 0 到 1000 或更多);不知道司法意见书中引用的案例最多
摘自JSON:
resource_url
id
absolute_url
cluster
author
joined_by
author_str
per_curiam
date_created
date_modified
type
sha1
page_count
download_url
local_path
plain_text
html
html_lawbox
html_columbia
html_with_citations
extracted_by_ocr
opinions_cited (sub nodes) [0] - [28]
我在合并目录时需要帮助(我尝试了在 google 和 Whosebug 上找到的各种合并解决方案;none 我对我的 cpu,内存或时间证明工作而不会花几个小时出错或最终什么也没产生)。
如何为 JSON 的每个文件夹创建 1 个大型 CSV(包含数万个;在本例中为 54k)1 JSON 为 CSV 中的每一行使用 JSON 创建列的元素名称。
我使用的 Whosebug 脚本(代码可以在这里看到我在评论中发布的错误):
import glob
import json
file_names = glob.glob('*.json')
json_list = []
for curr_f_name in file_names:
with open(curr_f_name) as curr_f_obj:
json_list.append(json.load(curr_f_obj))
with open('json_merge_out.json', 'w') as out_file:
json.dump(json_list, out_file, indent=4)
以上尝试补救措施输出以下错误:
/Wash/json# ./json.merge.python.1.py
./json.merge.python.1.py: line 4: syntax error near unexpected token `('
./json.merge.python.1.py: line 4: `file_names = glob.glob('*.json')'
这是一个使用 jq 的快速解决方案。它几乎不需要任何内存,但有一般警告和一个潜在的并发症。
需要注意的是,假设“joined_by”数组可以使用“;”作为分隔符展开为字符串。
复杂的是一些 CSV 解析器需要“矩形”结构。在下面的第一个可能的解决方案中,生成的 header 将仅考虑
显示的第一个文件中的“opinions_cited”数组。如果以后 JSON 个文件包含更多
“opinions_cited”,行仍然是正确的,但 header 不会考虑它们。
如果 header 是一个问题,那么您可能希望考虑 two-pass 解决方案以避免内存问题。如本答案的第 2 部分所示,第一遍将负责
确定最大数组长度,
在第二遍中,该值将用于确定适当的 headers.
您可能还希望考虑 post-processing“修正”。
为了测试,我建议使用 topKeys
的截断版本,例如
def topKeys: {resource_url, opinions_cited};
第 1 部分 - one-pass 方法
在所有 .json 文件所在的目录中调用 jq 测试了以下内容:
jq -Mnrf combine.jq *.json > wash.csv
combine.jq
def topKeys: {
resource_url,
id,
absolute_url,
cluster,
author,
joined_by,
author_str,
per_curiam,
date_created,
date_modified,
type,
sha1,
page_count,
download_url,
local_path,
plain_text,
html,
html_lawbox,
html_columbia,
html_with_citations,
extracted_by_ocr
}
| .joined_by |= (if type == "array" then join("; ") else . end)
;
def header:
(topKeys|keys_unsorted) + [range(1; 1 + (.opinions_cited | length)) ];
def row:
[topKeys[]] + .opinions_cited;
# s should be a stream of arrays
# For each item in the stream, a counter (starting at 1) is inserted before the other items
def insert_counter(s): foreach s as $x (0; .+1; [.] + $x);
# Read the first file for the headers
input
| (["record"] + header),
insert_counter( (., inputs) | row )
| @csv
第 2 部分 - two-pass 解决方案
(a) 将上面header
的def改成:
def header:
(topKeys|keys_unsorted) + [range(1; 1 + $n) ];
(b) 使用或改编以下脚本:
#!/bin/bash
n=$(jq 'def max(s): reduce s as $x (null; if . == null or $x > . then $x else . end); max(.opinions_cited|length)' *.json )
jq -Mnr --argjson n $n -f combine.jq *.json > wash.csv
备案...
有很多 post-processing 选项。一种是使用csvq,例如:
csvq --allow-uneven-fields -f CSV 'select *' < wash.csv | sponge wash.csv
我正在努力使主要来源美国法律更符合美国残疾人法案 (ADA),更符合我的研究。
技术问题在主题中。
我正在使用的源文件可以在这里找到:https://www.courtlistener.com/api/bulk-data/opinions/wash.tar.gz
该档案中的示例 JSON 文件(其中包含 52,565 条华盛顿州最高法院的司法意见),
987095.json 是一个包含以下“元素”的示例(我想将元素名称作为列名传递,同时为记录计数提供新的 ID;而不是源数据库 ID 列):
使用 Dadroit Viewer 1.5 Build 1935.appimage 查看 JSON 数据对我来说最简单。
我提取了以下数据(底部 opinions_cited 有 [] 括号,其中包含 0 - 28;我希望每个 JSON 都有不同数量的 opinions_cited ;任何人从 0 到 1000 或更多);不知道司法意见书中引用的案例最多
摘自JSON:
resource_url
id
absolute_url
cluster
author
joined_by
author_str
per_curiam
date_created
date_modified
type
sha1
page_count
download_url
local_path
plain_text
html
html_lawbox
html_columbia
html_with_citations
extracted_by_ocr
opinions_cited (sub nodes) [0] - [28]
我在合并目录时需要帮助(我尝试了在 google 和 Whosebug 上找到的各种合并解决方案;none 我对我的 cpu,内存或时间证明工作而不会花几个小时出错或最终什么也没产生)。
如何为 JSON 的每个文件夹创建 1 个大型 CSV(包含数万个;在本例中为 54k)1 JSON 为 CSV 中的每一行使用 JSON 创建列的元素名称。
我使用的 Whosebug 脚本(代码可以在这里看到我在评论中发布的错误):
import glob
import json
file_names = glob.glob('*.json')
json_list = []
for curr_f_name in file_names:
with open(curr_f_name) as curr_f_obj:
json_list.append(json.load(curr_f_obj))
with open('json_merge_out.json', 'w') as out_file:
json.dump(json_list, out_file, indent=4)
以上尝试补救措施输出以下错误:
/Wash/json# ./json.merge.python.1.py
./json.merge.python.1.py: line 4: syntax error near unexpected token `('
./json.merge.python.1.py: line 4: `file_names = glob.glob('*.json')'
这是一个使用 jq 的快速解决方案。它几乎不需要任何内存,但有一般警告和一个潜在的并发症。
需要注意的是,假设“joined_by”数组可以使用“;”作为分隔符展开为字符串。
复杂的是一些 CSV 解析器需要“矩形”结构。在下面的第一个可能的解决方案中,生成的 header 将仅考虑 显示的第一个文件中的“opinions_cited”数组。如果以后 JSON 个文件包含更多 “opinions_cited”,行仍然是正确的,但 header 不会考虑它们。
如果 header 是一个问题,那么您可能希望考虑 two-pass 解决方案以避免内存问题。如本答案的第 2 部分所示,第一遍将负责 确定最大数组长度, 在第二遍中,该值将用于确定适当的 headers.
您可能还希望考虑 post-processing“修正”。
为了测试,我建议使用 topKeys
的截断版本,例如
def topKeys: {resource_url, opinions_cited};
第 1 部分 - one-pass 方法
在所有 .json 文件所在的目录中调用 jq 测试了以下内容:
jq -Mnrf combine.jq *.json > wash.csv
combine.jq
def topKeys: {
resource_url,
id,
absolute_url,
cluster,
author,
joined_by,
author_str,
per_curiam,
date_created,
date_modified,
type,
sha1,
page_count,
download_url,
local_path,
plain_text,
html,
html_lawbox,
html_columbia,
html_with_citations,
extracted_by_ocr
}
| .joined_by |= (if type == "array" then join("; ") else . end)
;
def header:
(topKeys|keys_unsorted) + [range(1; 1 + (.opinions_cited | length)) ];
def row:
[topKeys[]] + .opinions_cited;
# s should be a stream of arrays
# For each item in the stream, a counter (starting at 1) is inserted before the other items
def insert_counter(s): foreach s as $x (0; .+1; [.] + $x);
# Read the first file for the headers
input
| (["record"] + header),
insert_counter( (., inputs) | row )
| @csv
第 2 部分 - two-pass 解决方案
(a) 将上面header
的def改成:
def header:
(topKeys|keys_unsorted) + [range(1; 1 + $n) ];
(b) 使用或改编以下脚本:
#!/bin/bash
n=$(jq 'def max(s): reduce s as $x (null; if . == null or $x > . then $x else . end); max(.opinions_cited|length)' *.json )
jq -Mnr --argjson n $n -f combine.jq *.json > wash.csv
备案...
有很多 post-processing 选项。一种是使用csvq,例如:
csvq --allow-uneven-fields -f CSV 'select *' < wash.csv | sponge wash.csv