Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/image/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用Java从json数据生成csv文件?_Java_Json_Jsonnode - Fatal编程技术网

如何使用Java从json数据生成csv文件?

如何使用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

我尝试从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,.....
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库来完成这个简单的示例。您更新的部件可能混合了这两者并使其复杂化。