Reputation: 113
I have the following class
public class Params {
private String dataType;
private Map<String, List<String>> group;
private List<Aggregate> aggregates;
private List<String> scene;
private List<String> company;
private List<Map<String, List<String>>> fit;
private Map<String, String> params;
private String tempo;
private String id;
private String valuation;
}
In order to convert it to a tsv, I have serialized it to json using:
public String put(final Params parameter) {
serializedParams = JsonSerializer.serialize(params);
}
So I get something like this as an output:
{
"dataType" : "abc",
"group" : { },
"aggregates" : [ ],
"scene" : [ "AC" ],
"company" : [ "pr" ],
"fit" : [ {
"prod" : [ "A1" ]
} ],
"params" : null,
"tempo" : "note",
"id" : "123",
"valuation" : USD
}
My eventual output is getting something like this (tab-separated):
abc AC pr prod A1 note 123 USD
I tried using :
parameter.getGroup.values()
This, however, only gives the values present in a format like [ val ].
How can I get all the values of the object simultaneously? Is it possible to get values from a map, list etc simultaneously without separate processing?
Any help would be appreciated.
Upvotes: 1
Views: 2392
Reputation: 842
Same CSV generate code you have to use, and only add a few things when you create the TSV file as below
try (CSVWriter writer = new CSVWriter(new FileWriter("src/main/resources/test2.tsv"),
'\t',
CSVWriter.NO_QUOTE_CHARACTER,
CSVWriter.DEFAULT_ESCAPE_CHARACTER,
CSVWriter.DEFAULT_LINE_END)) {
writer.writeAll(dataLines);
}
I used OpenCsV maven library
Upvotes: 0
Reputation: 4713
It's not quite clear from your question exactly how you want to handle your data when generating your tabbed output for certain scenarios, but I'll try to provide some sample code to help you.
First, however, I want to say that it's not a good idea to serialize to JSON and then serialize JSON to tab separated values. You're doing 2 steps when you could be doing one, the JSON serialization doesn't get you any closer to your goal, and serialization is generally a costly process - you don't want to do it more than you have to.
So with that in mind here's a quick example of how you might implement a simple tab delimited serialization:
Since you have at least one custom object to deal with inside of your Params
class (referring to the List
of Aggregate
objects) I would suggest creating an interface that your classes can implement to indicate they are able to be serialized into a tab delimited string.
I simply called this interface TabSerializable
:
public interface TabSerializable {
public String toTabbedString();
}
Next, I modified your Params
class to implement this interface:
public class Params implements TabSerializable{
//fields omitted for brevity.
...
public String toTabbedString(){
StringJoiner joiner = new StringJoiner("\t");
TabSerializer.addValue(dataType, joiner);
TabSerializer.addValue(group, joiner);
TabSerializer.addValue(aggregates, joiner);
TabSerializer.addValue(scene, joiner);
TabSerializer.addValue(company, joiner);
TabSerializer.addValue(fit, joiner);
TabSerializer.addValue(params, joiner);
TabSerializer.addValue(tempo, joiner);
TabSerializer.addValue(id, joiner);
TabSerializer.addValue(valuation, joiner);
return joiner.toString();
}
...
}
I also created a sample Aggregate
class which also implements this interface:
public class Aggregate implements TabSerializable{
private String data;
@Override
public String toTabbedString() {
return data;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
}
Since you have mostly generic types of data structures like maps and lists I created the TabSerializer
class to help transform those structures into tab delimited strings:
import java.util.List;
import java.util.Map;
import java.util.StringJoiner;
public class TabSerializer {
private static void addValuesFromMap(Map<?,?> obj, StringJoiner joiner) {
for(Object key: obj.keySet()){
Object value = obj.get(key);
if(value == null){
continue;
}
addValue(key, joiner);
addValue(value, joiner);
}
}
private static void addValuesFromList(List<?> arr, StringJoiner joiner) {
for(int i=0; i<arr.size(); i++){
Object value = arr.get(i);
addValue(value, joiner);
}
}
public static void addValue(Object value, StringJoiner joiner){
if(value == null){
return;
}
if(value instanceof List){
addValuesFromList((List<?>)value, joiner);
}else if(value instanceof Map){
addValuesFromMap((Map<?,?>)value, joiner);
}else if(value instanceof TabSerializable){
joiner.add(((TabSerializable) value).toTabbedString());
}else{
joiner.add(String.valueOf(value));
}
}
}
Based on the example you gave in your question I wrote the logic above to skip null values and the names of fields at the top level (those fields in the Params
class).
Finally I created a class with a main
to test the above logic:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MainTabDelim {
public static void main(String[] args) {
Params params = new Params();
params.setDataType("abc");
List<String> scene = new ArrayList<>();
scene.add("AC");
params.setScene(scene);
List<String> company = new ArrayList<>();
company.add("pr");
params.setCompany(company);
List<Map<String, List<String>>> fit = new ArrayList<>();
List<String> fitInner = new ArrayList<>();
fitInner.add("A1");
Map<String, List<String>> fitMap = new HashMap<>();
fitMap.put("prod", fitInner);
fit.add(fitMap);
params.setFit(fit);
params.setTempo("note");
params.setId("123");
params.setValuation("USD");
// Uncomment the following lines to see how Aggregate works:
// List<Aggregate> aggregates = new ArrayList<>();
// Aggregate ag = new Aggregate();
// ag.setData("some_data");
// aggregates.add(ag);
// params.setAggregates(aggregates);
System.out.println(params.toTabbedString());
}
}
The output is:
abc AC pr prod A1 note 123 USD
I hope this helps you to get started. Enjoy!
Upvotes: 2