【发布时间】:2020-09-26 06:35:44
【问题描述】:
我尝试从 json 类型数据生成 csv 文件。这些是我的 json 测试数据。
{
"realtime_start":"2020-09-25",
"realtime_end":"2020-09-25",,
"units": "Percent",
"seriess": [
{
"name": "James",
"age": 29,
"house": "CA"
},
{
"name": "Jina",
"age": 39,
"house": "MA",
"notes": "Million tonne punch"
},
}
问题是 json 数组类型 "seriess" 在所有节点中都不包含 "notes" 节点。
我制作了以下 java 代码来将此 json 数据更改为带有标题列的 csv 文件
JSONObject json = getJsonFileFromURL(...)
JSONArray docsArray = json.getJSONArray("seriess");
docsArray.put(json.get("realtime_start"));
docsArray.put(json.get("realtime_end"));
docsArray.put(json.get("units"));
JsonNode jsonTree = new ObjectMapper().readTree(docsArray.toString());
Builder csvSchemaBuilder = CsvSchema.builder();
for(JsonNode node : jsonTree) {
node.fieldNames().forEachRemaining(fieldName -> {csvSchemaBuilder.addColumn(fieldName);} );
}
CsvSchema csvSchema = csvSchemaBuilder.build().withHeader();
CsvMapper csvMapper = new CsvMapper();
csvMapper.writerFor(JsonNode.class).with(csvSchema).writeValue(new File("test.csv"), jsonTree);
但不正确的结果如下所示,
realtime_start,realtime_end,units,names,age,house,realtime_start,realtime_end,units,names,age,house,notes, realtime_start,.....
生成的标题列不包含不同的值。标题列是重复添加的。如何生成如下所示的不同标头
realtime_start,realtime_end,units,names,age,house, notes
有什么想法吗?
更新部分
我尝试从 FRED(圣路易斯联邦储备银行)提取数据。 FRED 提供如下简单方便的 Python api,
from fredapi import Fred
import pandas as pd
fred = Fred(api_key='abcdefghijklmnopqrstuvwxyz0123456789')
data_unemploy = fred.search('Unemployment Rate in California')
data_unemploy.to_csv("test_unemploy.csv")
但是 Java api 已被弃用,所以我必须开发简单的 Java api,将 json 值转换为 csv 文件。我通过谷歌搜索找到了以下 Java 代码
JSONObject json = getJsonFileFromURL("https://api.stlouisfed.org/fred/series/search?search_text=Unemployment+Rate+in+California&api_key=abcdefghijklmnopqrstuvwxyz0123456789&file_type=json");
JSONArray docsArray = json.getJSONArray("seriess");
docsArray.put(json.get("realtime_start"));
docsArray.put(json.get("realtime_end"));
JsonNode jsonTree = new ObjectMapper().readTree(docsArray.toString());
JsonNode firstObject = jsonTree.elements().next(); // I am struggling with this line
firstObject.fieldNames().forEachRemaining(fieldName -> {csvSchemaBuilder.addColumn(fieldName);} );
CsvSchema csvSchema = csvSchemaBuilder.build().withHeader();
CsvMapper csvMapper = new CsvMapper();
csvMapper.writerFor(JsonNode.class).with(csvSchema).writeValue(new File("test.csv"), jsonTree);
从 json 数据中提取列 JsonNode firstObject = jsonTree.elements().next(); 返回第一个 json 节点。但是这一行不返回notes 列。因为第一行不包含notes 键值。
所以我将此代码行更改为以下行
for(JsonNode node : jsonTree) {
node.fieldNames().forEachRemaining(fieldName -> {
csvSchemaBuilder.addColumn(fieldName);
} );
}
但是这些行抛出了我没想到的结果。重复的重复列如下所示
realtime_start,realtime_end,units,names,age,house,realtime_start,realtime_end,units,names,age,house,notes, realtime_start,.....
我完全被这部分卡住了。
【问题讨论】:
-
你期待什么?您是否正确考虑过这一点,您正在将一个复杂的结构展平为单行,因此您需要制定一个策略来为数组中的每个元素创建一个新行,并在多行中包含来自数组外部的值。您还需要跟踪所有可能的列,并确保写入默认值,以防 json 中缺少值。