如何使用Java从json数据生成csv文件?
我尝试从json类型的数据生成csv文件。这些是我的json测试数据如何使用Java从json数据生成csv文件?,java,json,jsonnode,Java,Json,Jsonnode,我尝试从json类型的数据生成csv文件。这些是我的json测试数据 { "realtime_start":"2020-09-25", "realtime_end":"2020-09-25",, "units": "Percent", "seriess": [ { "name": "James
{
"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,.....
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")
生成的标题列不包含不同的值。标题列添加为两列。如何生成如下所示的不同的标题
realtime_start,realtime_end,units,names,age,house, notes
realtime_start,realtime_end,units,names,age,house,realtime_start,realtime_end,units,names,age,house,notes, realtime_start,.....
有什么想法吗
更新部分
我试图从弗雷德(圣路易斯联邦储备银行)那里提取数据。FRED提供了简单方便的Python api,如下所示:
realtime_start,realtime_end,units,names,age,house,realtime_start,realtime_end,units,names,age,house,notes, realtime_start,.....
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")
但是JavaAPI已经被弃用了,所以我必须开发简单的JavaAPI,将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
列。因为第一行不包含注释
键值
所以我把这一行代码改为以下几行
for(JsonNode node : jsonTree) {
node.fieldNames().forEachRemaining(fieldName -> {
csvSchemaBuilder.addColumn(fieldName);
} );
}
但是,这些线抛出的结果,我并不期望。重复的重复列如下所示
realtime_start,realtime_end,units,names,age,house, notes
realtime_start,realtime_end,units,names,age,house,realtime_start,realtime_end,units,names,age,house,notes, realtime_start,.....
我完全被这部分卡住了。您可以使用ApacheCommons IO库来完成
pom.xml
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
输出
最容易编写如下所示的bin类型类:
public class CsvVo {
private String realtime_start;
private String realtime_end;
private String units;
private String name;
private String age;
private String house;
private String notes;
public void setRealtime_start(String realtime_start) {
this.realtime_start = realtime_start;
}
//Other getters and Setters
public static <T> void csvWriterUtil(Class<T> beanClass, List<T> data, String outputFile, String[] columnMapping){
try{
Writer writer = new BufferedWriter(new FileWriter(outputFile));
ColumnPositionMappingStrategy<T> strategy = new ColumnPositionMappingStrategy<>();
strategy.setType(beanClass);
strategy.setColumnMapping(columnMapping);
StatefulBeanToCsv<T> statefulBeanToCsv =new StatefulBeanToCsvBuilder<T>(writer)
.withMappingStrategy(strategy)
.build();
writer.write(String.join(",",columnMapping)+"\n");
statefulBeanToCsv.write(data);
writer.close();
} catch (IOException e) {
e.printStackTrace();
} catch (CsvRequiredFieldEmptyException e) {
e.printStackTrace();
} catch (CsvDataTypeMismatchException e) {
e.printStackTrace();
}
}
然后你可以写:
public class ConvertJsonToCSVTest {
public static void main(String[] args) throws JSONException {
String jsonArrayString = "{\n" +
"\t\"realtime_start\": \"2020-09-25\",\n" +
"\t\"realtime_end\": \"2020-09-25\",\n" +
"\t\"units\": \"Percent\",\n" +
"\t\"seriess\": [{\n" +
"\t\t\t\"name\": \"James\",\n" +
"\t\t\t\"age\": 29,\n" +
"\t\t\t\"house\": \"CA\"\n" +
"\t\t},\n" +
"\t\t{\n" +
"\t\t\t\"name\": \"Jina\",\n" +
"\t\t\t\"age\": 39,\n" +
"\t\t\t\"house\": \"MA\",\n" +
"\t\t\t\"notes\": \"Million tonne punch\"\n" +
"\t\t}\n" +
"\t]\n" +
"}";
JSONObject inJson;
List<CsvVo> list = new ArrayList<>();
inJson = new JSONObject(jsonArrayString);
JSONArray inJsonSeries = inJson.getJSONArray("seriess");
for (int i = 0, size = inJsonSeries.length(); i < size; i++){
CsvVo line = new CsvVo();
line.setRealtime_start(inJson.get("realtime_start").toString());
line.setRealtime_end(inJson.get("realtime_end").toString());
line.setUnits(inJson.get("units").toString());
JSONObject o = (JSONObject)inJsonSeries.get(i);
line.setName(o.get("name").toString());
line.setAge(o.get("age").toString());
line.setHouse(o.get("house").toString());
try {
line.setNotes(o.get("notes").toString());
}catch (JSONException e){
line.setNotes("");
}
list.add(line);
}
String[] cols = {"realtime_start", "realtime_end", "units", "name", "age", "house", "notes"};
CsvUtils.csvWriterUtil(CsvVo.class, list, "in/EmpDetails.csv", cols);
}
}
public类ConvertJsonToCSVTest{
公共静态void main(字符串[]args)抛出JSONException{
字符串jsonArrayString=“{\n”+
“\t\“实时启动”:“2020-09-25\”,\n”+
“\t\'realtime\u end\:\'2020-09-25\,\n”+
\t“单位”:“百分比”,\n+
“\t\“seriess\”:[{\n”+
“\t\t\t\'name\:\'James\,\n”+
\t\t\t\“年龄\”:29,\n+
“\t\t\t\'house\':\'CA\'\n”+
\t\t}\n+
“\t\t{\n”+
“\t\t\t\'name\:\'Jina\,\n”+
\t\t\t\“年龄\”:39,\n+
“\t\t\t\'house\:\'MA\,\n”+
“\t\t\t\'notes\':\'Million tone punch\”\n”+
“\t\t}\n”+
“\t]\n”+
"}";
JSONObject inJson;
列表=新的ArrayList();
inJson=新的JSONObject(jsonArrayString);
JSONArray inJsonSeries=inJson.getJSONArray(“序列”);
for(int i=0,size=inJsonSeries.length();i
csvWriterUtil如下所示:
public class CsvVo {
private String realtime_start;
private String realtime_end;
private String units;
private String name;
private String age;
private String house;
private String notes;
public void setRealtime_start(String realtime_start) {
this.realtime_start = realtime_start;
}
//Other getters and Setters
public static <T> void csvWriterUtil(Class<T> beanClass, List<T> data, String outputFile, String[] columnMapping){
try{
Writer writer = new BufferedWriter(new FileWriter(outputFile));
ColumnPositionMappingStrategy<T> strategy = new ColumnPositionMappingStrategy<>();
strategy.setType(beanClass);
strategy.setColumnMapping(columnMapping);
StatefulBeanToCsv<T> statefulBeanToCsv =new StatefulBeanToCsvBuilder<T>(writer)
.withMappingStrategy(strategy)
.build();
writer.write(String.join(",",columnMapping)+"\n");
statefulBeanToCsv.write(data);
writer.close();
} catch (IOException e) {
e.printStackTrace();
} catch (CsvRequiredFieldEmptyException e) {
e.printStackTrace();
} catch (CsvDataTypeMismatchException e) {
e.printStackTrace();
}
}
publicstaticvoidcsvwriterutil(类beanClass,列表数据,字符串outputFile,字符串[]列映射){
试一试{
Writer-Writer=new-BufferedWriter(new-FileWriter(outputFile));
ColumnPositionMappingStrategy=新ColumnPositionMappingStrategy();
策略.setType(beanClass);
策略。setColumnMapping(columnMapping);
StatefulBeanToCsv StatefulBeanToCsv=新的StatefulBeanToCsvBuilder(编写器)
.withMappingStrategy(策略)
.build();
writer.write(String.join(“,”,columnMapping)+“\n”);
statefulBeanToCsv.write(数据);
writer.close();
}捕获(IOE异常){
e、 printStackTrace();
}捕获(CsvRequiredFieldEmptyException e){
e、 printStackTrace();
}捕获(CsvDataTypeMismatchException e){
e、 printStackTrace();
}
}
完整的示例可在中找到。您期望什么?您是否正确地考虑了这一点,您正在将一个复杂的结构展平到一行,因此您需要有一个策略,用于为数组中的每个元素创建新行,并在多行中包含来自数组外部的值。您还需要跟踪所有可能的列,并确保写入默认值,以防json中缺少值。感谢您的回复。我还有更多的问题。在上面的问题中,我的输入json数据类型只是字符串。但在我的项目中,我的输入源是包含数百个json数据的文本文件。所以,csv文件的列标题会在和上重复生成。如何删除重复的列值,从而获得不同的标题列值?您可以编写一个函数逐行读取文件(假设每行一个Json字符串),并从该函数返回列表。然后把名单传给鲁蒂尔公司。如果对你有帮助,请告诉我。亲爱的,@soumya kole,请检查我更新的部分并留下你的建议。你想用什么。如果您想使用Jackson,那么可以使用它或org.json库来完成这个简单的示例。您更新的部件可能混合了这两者并使其复杂化。