[英]Convert flattened CSV to nested JSON
I want to create a nested JSON from a flattened CSV:我想从扁平的 CSV 创建一个嵌套的 JSON:
CSV: CSV:
name address_city address_state
John Mumbai MH
John Bangalore KA
Bill Chennai TN
JSON: JSON:
[
{
"name": "John",
"address": [
{
"city": "Mumbai",
"state": "MH"
},
{
"city": "Bangalore",
"state": "KA"
}
]
},
{
"name": "Bill",
"address": [
{
"city": "Chennai",
"state": "TN"
}
]
}
]
I'm using univocity parser with @Nested annotation like this:我正在使用带有 @Nested 注释的单义性解析器,如下所示:
@Nested(headerTransformer = AddressTypeTransformer.class, args = "address")
private Address address;
and I'm getting JSON output as below, which has the address object and not array which is perfectly fine:我得到 JSON output 如下,它的地址是 object 而不是数组,这很好:
[
{
"name": "John",
"address": {
"city": "Mumbai",
"state": "MH"
}
},
{
"name": "John",
"address": {
"city": "Mumbai",
"state": "MH"
}
},
{
"name": "Bill",
"address": {
"city": "Chennai",
"state": "TN"
}
}
]
But when i change the code to make the address as array:但是当我更改代码以将地址设为数组时:
@Nested(headerTransformer = AddressTypeTransformer.class, args = "address")
private Address[] address;
I get following error:我收到以下错误:
Exception in thread "main" com.univocity.parsers.common.DataProcessingException: Unable to instantiate class '[Lcom.ss.beans.Address;'
Internal state when error was thrown: line=2, column=0, record=1, charIndex=58, headers=[id, name, address_city, address_state],
Why the @Nested annotation is not working with arrays/lists?为什么@Nested 注释不适用于数组/列表? How can I solve this problem?
我怎么解决这个问题? Is there any other way to solve this problem without using univocity?
有没有其他方法可以在不使用单义性的情况下解决这个问题?
PS: I'm asking this question after following the reply from @Jeronimo Backes in this post: Convert CSV data into nested json objects using java library PS:我在遵循@Jeronimo Backes 在这篇文章中的回复后提出这个问题: Convert CSV data into nested json objects using java library
Here is my approach:这是我的方法:
The test data (in my case, the fields are tab-separated):测试数据(在我的情况下,字段是制表符分隔的):
name address_city address_state
John Mumbai MH
John Bangalore KA
Bill Chennai TN
The imports I used:我使用的进口:
import com.google.gson.Gson;
import com.univocity.parsers.common.processor.BeanListProcessor;
import com.univocity.parsers.csv.CsvParser;
import com.univocity.parsers.csv.CsvParserSettings;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
The processing code:处理代码:
//
// parse the source file into a list of SourceRecord beans:
//
Reader reader = new FileReader(new File("C:/tmp/univocity_demo.csv"), StandardCharsets.UTF_8);
BeanListProcessor<SourceRecord> processor = new BeanListProcessor<>(SourceRecord.class);
CsvParserSettings parserSettings = new CsvParserSettings();
parserSettings.getFormat().setDelimiter("\t"); // tab separated data
parserSettings.getFormat().setLineSeparator("\n");
parserSettings.setProcessor(processor);
CsvParser parser = new CsvParser(parserSettings);
parser.parse(reader);
List<SourceRecord> sourceRecords = processor.getBeans();
//
// process those SourceRecord objects into consolidated Name beans:
//
Map<String, Name> namesMap = new HashMap<>();
sourceRecords.forEach(sourceRecord -> {
String sourceName = sourceRecord.getName();
if (namesMap.containsKey(sourceName)) {
namesMap.get(sourceName).getAddresses().add(sourceRecord.getAddress());
} else {
Name name = new Name();
name.setName(sourceName);
name.getAddresses().add(sourceRecord.getAddress());
namesMap.put(sourceName, name);
}
});
//
// convert to JSON:
///
Gson gson = new Gson();
String json = gson.toJson(namesMap.values());
The SourceRecord
bean is as follows. SourceRecord
bean 如下所示。 Note that we do not need anything other than the basic @Nested
annotation, here:请注意,除了基本的
@Nested
注释之外,我们不需要任何其他东西,这里:
public class SourceRecord {
@Parsed(field = "name")
private String name;
@Nested
private Address address;
// getters/setters not shown
}
Here are the output Name
and Address
beans.这是 output
Name
和Address
bean。 Note I am using the field name addresses
(not address
) in the Name
bean:注意我在
Name
bean 中使用字段名称addresses
(不是address
):
public class Name {
private String name;
private final List<Address> addresses = new ArrayList<>();
// getters/setters not shown
}
And the Address
bean - this is used both for the final output and also when reading the source file (hence the annotations are needed): Address
bean - 这既用于最终的 output 也用于读取源文件(因此需要注释):
public class Address {
@Parsed(field = "address_city")
private String city;
@Parsed(field = "address_state")
private String state;
// getters/setters not shown
}
The final JSON is:最终的 JSON 是:
[{
"name": "John",
"addresses": [{
"city": "Mumbai",
"state": "MH"
}, {
"city": "Bangalore",
"state": "KA"
}]
}, {
"name": "Bill",
"addresses": [{
"city": "Chennai",
"state": "TN"
}]
}]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.